sgsnemu: Fix wrong assumption always Interface Identifier == IPv6 public prefix
osmo-ggsn currently (20539f02713fc5a1f8f2248555d4a199e57cda98) uses same 64 bits value in the Interface Identifier (IPv6 GTP EUA sent during Create Pdp Ctx Response) as well as later for the IPv6 prefix (during Router Advertisement).
That's really an implementation details and it doesn't necessarily need to be the case as per spec (they can have totally different values). For instance, ergw uses a constant Interface identifier of ::1 for all UEs.
sgsnemu currently expects the Interface Identifier to be the same as the IPv6 public prefix later received, which means it won't work properly when used against ergw (on IPv6).
Probably this diff for osmo-ggsn allows quickly running into a similar scenario in sgsnemu (receiving different values):
diff --git a/ggsn/icmpv6.c b/ggsn/icmpv6.c index 12119b8..240c89c 100644 --- a/ggsn/icmpv6.c +++ b/ggsn/icmpv6.c @@ -142,6 +142,7 @@ struct msgb *icmpv6_construct_ra(const struct in6_addr *saddr, ra_opt_pref->preferred_lifetime = htonl(GGSN_AdvPreferredLifetime); ra_opt_pref->res2 = 0; memcpy(ra_opt_pref->prefix, prefix, sizeof(ra_opt_pref->prefix)); + ra_opt_pref->prefix ^= 0xff; /* checksum */ skb_csum = csum_partial(msgb_data(msg), msgb_length(msg), 0);
Disable handling of routing advertisement by the kernel (SLAAC) and do it within sgsnemu .
- Upon IPv6 packet received in GTP tunnel from SGSN, where normally we'd then forward it to the tun device (encaps_tun()), instead we pass it to handle_router_mcast() (tun.c).
- In handle_router_mcast(), if what we received is a RouterSolicitation, parse it and send back on the GTP tunnel a RouterAdvertisement: gtp_data_req(icmpv6_construct_ra())
- Have a working setup with sgsnemu and osmo-ggsn
- Trigger the issue by applying the patch above mentioned to study the behavior
- Disable SLAAC (RouterAdvertisement) in the tun interface:
- Add a proc_ipv6_conf_write() function similar to the aleady available proc_ipv6_conf_read()
- Redo the checks on "accept_ra" and "forwarding" proc properties in create_pdp_conf().
- Send a RouterSolicitiation over the GTP tunnel using the IPv6 EUA received in PDPCreateContextResponse (create_pdp_conf()).
- Wait for RouterAdvertisement coming from the GTP tunnel, then set the IP address prefix from there (cb_tun_ind()).
Extra: This allows us to implement IPv6 builtin ping in sgsemu (like we do already for IPv4) without requiring the tun iface.