pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ggsn/+/38470?usp=email )
Change subject: ggsn: Support announcing APN MTU over ICMPv6 RA ......................................................................
ggsn: Support announcing APN MTU over ICMPv6 RA
Related: OS#6298 Related: SYS#7122 Change-Id: I8bb67915dd5f39ad9ffb80e5aaf9af1e7d70c96c --- M ggsn/ggsn.c M lib/icmpv6.c M lib/icmpv6.h 3 files changed, 33 insertions(+), 3 deletions(-)
Approvals: lynxis lazus: Looks good to me, but someone else must approve Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved osmith: Looks good to me, but someone else must approve
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c index 4dc0c94..19b0132 100644 --- a/ggsn/ggsn.c +++ b/ggsn/ggsn.c @@ -774,7 +774,7 @@ /* daddr: all-routers multicast addr */ if (IN6_ARE_ADDR_EQUAL(&ip6h->ip6_dst, &all_router_mcast_addr)) return handle_router_mcast(pdp->gsn, pdp, &peer->addr.v6, - &apn->v6_lladdr, pack, len); + &apn->v6_lladdr, apn->cfg.mtu, pack, len); break; case 4: peer = pdp_get_peer_ipv(pdp, false); diff --git a/lib/icmpv6.c b/lib/icmpv6.c index b6994cd..e74fb70 100644 --- a/lib/icmpv6.c +++ b/lib/icmpv6.c @@ -94,11 +94,13 @@ * \returns callee-allocated message buffer containing router advertisement */ static struct msgb *icmpv6_construct_ra(const struct in6_addr *saddr, const struct in6_addr *daddr, - const struct in6_addr *prefix) + const struct in6_addr *prefix, + uint32_t mtu) { struct msgb *msg = msgb_alloc_headroom(512,128, "IPv6 RA"); struct icmpv6_radv_hdr *ra; struct icmpv6_opt_prefix *ra_opt_pref; + struct icmpv6_opt_mtu *ra_opt_mtu;
OSMO_ASSERT(msg);
@@ -135,6 +137,25 @@ ra_opt_pref->res2 = 0; memcpy(ra_opt_pref->prefix, prefix, sizeof(ra_opt_pref->prefix));
+ /* RFC4861 Section 4.6.4, MTU */ + ra_opt_mtu = (struct icmpv6_opt_mtu *) msgb_put(msg, sizeof(*ra_opt_mtu)); + ra_opt_mtu->hdr.type = 5; /* RFC4861 4.6.4 */ + ra_opt_mtu->hdr.len = 1; /* RFC4861 4.6.4 */ + ra_opt_mtu->reserved = 0; + ra_opt_mtu->mtu = htonl(mtu); + + /* The Prefix is contained in the Prefix Information Option of + * the Router Advertisements and shall have the A-flag set + * and the L-flag cleared */ + ra_opt_pref->a = 1; + ra_opt_pref->l = 0; + ra_opt_pref->res = 0; + /* The lifetime of the prefix shall be set to infinity */ + ra_opt_pref->valid_lifetime = htonl(GGSN_AdvValidLifetime); + ra_opt_pref->preferred_lifetime = htonl(GGSN_AdvPreferredLifetime); + ra_opt_pref->res2 = 0; + memcpy(ra_opt_pref->prefix, prefix, sizeof(ra_opt_pref->prefix)); + /* checksum */ ra->hdr.csum = icmpv6_prepend_ip6hdr(msg, saddr, daddr);
@@ -194,6 +215,7 @@ int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const struct in6_addr *pdp_prefix, const struct in6_addr *own_ll_addr, + uint32_t mtu, const uint8_t *pack, unsigned len) { const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack; @@ -230,7 +252,7 @@ /* Send router advertisement from GGSN link-local * address to MS link-local address, including prefix * allocated to this PDP context */ - msg = icmpv6_construct_ra(own_ll_addr, &ip6h->ip6_src, pdp_prefix); + msg = icmpv6_construct_ra(own_ll_addr, &ip6h->ip6_src, pdp_prefix, mtu); /* Send the constructed RA to the MS */ gtp_data_req(gsn, pdp, msgb_data(msg), msgb_length(msg)); msgb_free(msg); diff --git a/lib/icmpv6.h b/lib/icmpv6.h index 5bed5c6..1040600 100644 --- a/lib/icmpv6.h +++ b/lib/icmpv6.h @@ -81,6 +81,13 @@ uint8_t prefix[16]; } __attribute__ ((packed));
+/* RFC4861 Section 4.6.4 */ +struct icmpv6_opt_mtu { + struct icmpv6_opt_hdr hdr; + uint16_t reserved; + uint32_t mtu; +} __attribute__ ((packed)); + uint16_t icmpv6_prepend_ip6hdr(struct msgb *msg, const struct in6_addr *saddr, const struct in6_addr *daddr);
@@ -89,6 +96,7 @@ int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const struct in6_addr *pdp_prefix, const struct in6_addr *own_ll_addr, + uint32_t mtu, const uint8_t *pack, unsigned len);
struct icmpv6_radv_hdr *icmpv6_validate_router_adv(const uint8_t *pack, unsigned len);