Please ignore this patch. The updated one is here - https://mail.openvswitch.org/pipermail/ovs-dev/2017-March/330135.html
Thanks Numan On Thu, Mar 23, 2017 at 11:33 AM, <nusid...@redhat.com> wrote: > From: Zong Kai LI <zealo...@gmail.com> > > This patch introduces methods to compose a Router Advertisement (RA) > packet, > introduces flags for RA. RA packet composed structures against > specification > in RFC4861. > > Caller can use compse_nd_ra_with_sll_mtu_opts to compose a RA packet with > Source Link-layer Address Option and MTU Option. > > Caller can use packet_put_ra_prefix_opt to append a Prefix Information > Option > to a RA packet. > > Signed-off-by: Zongkai LI <zealo...@gmail.com> > --- > lib/packets.c | 88 ++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++ > lib/packets.h | 59 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 147 insertions(+) > > diff --git a/lib/packets.c b/lib/packets.c > index 94e7d87..dbe5105 100644 > --- a/lib/packets.c > +++ b/lib/packets.c > @@ -35,6 +35,7 @@ > > const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT; > const struct in6_addr in6addr_all_hosts = IN6ADDR_ALL_HOSTS_INIT; > +const struct in6_addr in6addr_all_routers = IN6ADDR_ALL_ROUTERS_INIT; > > struct in6_addr > flow_tnl_dst(const struct flow_tnl *tnl) > @@ -1428,6 +1429,93 @@ compose_nd_na(struct dp_packet *b, > ND_MSG_LEN + > ND_OPT_LEN)); > } > > +/* Compose an IPv6 Neighbor Discovery Router Advertisement message with > + * Source Link-layer Address Option and MTU Option. > + * Caller can call packet_put_ra_prefix_opt to append Prefix Information > + * Options to composed messags in 'b'. */ > +void > +compose_nd_ra_with_sll_mtu_opts(struct dp_packet *b, > + const struct eth_addr eth_src, > + const struct eth_addr eth_dst, > + const struct in6_addr *ipv6_src, > + const struct in6_addr *ipv6_dst, > + uint8_t cur_hop_limit, uint8_t mo_flags, > + ovs_be16 router_lt, ovs_be32 > reachable_time, > + ovs_be32 retrans_timer, ovs_be32 mtu) > +{ > + struct ovs_ra_msg *ra; > + struct ovs_nd_mtu_opt *mtu_opt; > + struct ovs_nd_opt *lla_opt; > + uint32_t icmp_csum; > + > + /* Don't compose Router Advertisement packet with MTU Option if mtu > + * value is 0. */ > + bool with_mtu = mtu != 0; > + size_t mtu_opt_len = with_mtu ? ND_MTU_OPT_LEN : 0; > + > + eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN); > + ra = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst, 0, 0, 255, > + RA_MSG_LEN + ND_OPT_LEN + mtu_opt_len); > + > + ra->icmph.icmp6_type = ND_ROUTER_ADVERT; > + ra->icmph.icmp6_code = 0; > + ra->cur_hop_limit = cur_hop_limit; > + ra->mo_flags = mo_flags; > + ra->router_lifetime = router_lt; > + ra->reachable_time = reachable_time; > + ra->retrans_timer = retrans_timer; > + > + lla_opt = &ra->options[0]; > + lla_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; > + lla_opt->nd_opt_len = 1; > + lla_opt->nd_opt_mac = eth_src; > + > + if (with_mtu) { > + /* ovs_nd_mtu_opt has the same size with ovs_nd_opt. */ > + mtu_opt = (struct ovs_nd_mtu_opt *)(lla_opt + 1); > + mtu_opt->type = ND_OPT_MTU; > + mtu_opt->len = 1; > + mtu_opt->reserved = 0; > + mtu_opt->mtu = mtu; > + } > + > + ra->icmph.icmp6_cksum = 0; > + icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b)); > + ra->icmph.icmp6_cksum = csum_finish(csum_continue( > + icmp_csum, ra, RA_MSG_LEN + ND_OPT_LEN + mtu_opt_len)); > +} > + > +/* Append an IPv6 Neighbor Discovery Prefix Information option to a > + * Router Advertisement message. */ > +void > +packet_put_ra_prefix_opt(struct dp_packet *b, > + uint8_t plen, uint8_t la_flags, ovs_be32 > valid_lifetime, > + ovs_be32 preferred_lifetime, const ovs_be128 > prefix) > +{ > + size_t prev_l4_size = dp_packet_l4_size(b); > + struct ip6_hdr *nh = dp_packet_l3(b); > + nh->ip6_plen = htons(prev_l4_size + ND_PREFIX_OPT_LEN); > + > + struct ovs_ra_msg *ra = dp_packet_l4(b); > + struct ovs_nd_prefix_opt *prefix_opt; > + uint32_t icmp_csum; > + > + prefix_opt = dp_packet_put_uninit(b, sizeof(struct > ovs_nd_prefix_opt)); > + prefix_opt->type = ND_OPT_PREFIX_INFORMATION; > + prefix_opt->len = 4; > + prefix_opt->prefix_len = plen; > + prefix_opt->la_flags = la_flags; > + prefix_opt->valid_lifetime = valid_lifetime; > + prefix_opt->preferred_lifetime = preferred_lifetime; > + prefix_opt->reserved = 0; > + memcpy(prefix_opt->prefix.be32, prefix.be32, sizeof(ovs_be32[4])); > + > + ra->icmph.icmp6_cksum = 0; > + icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b)); > + ra->icmph.icmp6_cksum = csum_finish(csum_continue( > + icmp_csum, ra, prev_l4_size + ND_PREFIX_OPT_LEN)); > +} > + > uint32_t > packet_csum_pseudoheader(const struct ip_header *ip) > { > diff --git a/lib/packets.h b/lib/packets.h > index a5a483b..b285185 100644 > --- a/lib/packets.h > +++ b/lib/packets.h > @@ -858,6 +858,33 @@ struct ovs_nd_opt { > }; > BUILD_ASSERT_DECL(ND_OPT_LEN == sizeof(struct ovs_nd_opt)); > > +/* Neighbor Discovery option: Prefix Information. */ > +#define ND_PREFIX_OPT_LEN 32 > +struct ovs_nd_prefix_opt { > + uint8_t type; /* ND_OPT_PREFIX_INFORMATION */ > + uint8_t len; /* The length of Prefix Information Option shoulud > be 4. */ > + uint8_t prefix_len; > + uint8_t la_flags; /* ND_PREFIX_ON_LINK and > ND_PREFIX_AUTONOMOUS_ADDRESS flags. */ > + ovs_be32 valid_lifetime; > + ovs_be32 preferred_lifetime; > + ovs_be32 reserved; /* Always should be 0. */ > + union ovs_16aligned_in6_addr prefix; > +}; > +BUILD_ASSERT_DECL(ND_PREFIX_OPT_LEN == sizeof(struct ovs_nd_prefix_opt)); > + > +#define ND_PREFIX_ON_LINK 0x80 > +#define ND_PREFIX_AUTONOMOUS_ADDRESS 0x40 > + > +/* Neighbor Discovery option: MTU. */ > +#define ND_MTU_OPT_LEN 8 > +struct ovs_nd_mtu_opt { > + uint8_t type; /* ND_OPT_MTU */ > + uint8_t len; /* The length of MTU Option shoulud be 1. */ > + ovs_be16 reserved; /* Always should be 0. */ > + ovs_be32 mtu; > +}; > +BUILD_ASSERT_DECL(ND_MTU_OPT_LEN == sizeof(struct ovs_nd_mtu_opt)); > + > /* Like struct nd_msg (from ndisc.h), but whereas that struct requires > 32-bit > * alignment, this one only requires 16-bit alignment. */ > #define ND_MSG_LEN 24 > @@ -869,10 +896,26 @@ struct ovs_nd_msg { > }; > BUILD_ASSERT_DECL(ND_MSG_LEN == sizeof(struct ovs_nd_msg)); > > +/* Neighbor Discovery packet flags. */ > #define ND_RSO_ROUTER 0x80000000 > #define ND_RSO_SOLICITED 0x40000000 > #define ND_RSO_OVERRIDE 0x20000000 > > +#define RA_MSG_LEN 16 > +struct ovs_ra_msg { > + struct icmp6_header icmph; > + uint8_t cur_hop_limit; > + uint8_t mo_flags; /* ND_RA_MANAGED_ADDRESS and ND_RA_OTHER_CONFIG > flags. */ > + ovs_be16 router_lifetime; > + ovs_be32 reachable_time; > + ovs_be32 retrans_timer; > + struct ovs_nd_opt options[0]; > +}; > +BUILD_ASSERT_DECL(RA_MSG_LEN == sizeof(struct ovs_ra_msg)); > + > +#define ND_RA_MANAGED_ADDRESS 0x80 > +#define ND_RA_OTHER_CONFIG 0x40 > + > /* > * Use the same struct for MLD and MLD2, naming members as the defined > fields in > * in the corresponding version of the protocol, though they are reserved > in the > @@ -927,6 +970,10 @@ extern const struct in6_addr in6addr_all_hosts; > #define IN6ADDR_ALL_HOSTS_INIT { { { 0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, > \ > 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 > } } } > > +extern const struct in6_addr in6addr_all_routers; > +#define IN6ADDR_ALL_ROUTERS_INIT { { { > 0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, > \ > + > 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 > } } } > + > static inline bool ipv6_addr_equals(const struct in6_addr *a, > const struct in6_addr *b) > { > @@ -1131,6 +1178,18 @@ void compose_nd_na(struct dp_packet *, const struct > eth_addr eth_src, > const struct in6_addr *ipv6_src, > const struct in6_addr *ipv6_dst, > ovs_be32 rso_flags); > +void compose_nd_ra_with_sll_mtu_opts(struct dp_packet *, > + const struct eth_addr eth_src, > + const struct eth_addr eth_dst, > + const struct in6_addr *ipv6_src, > + const struct in6_addr *ipv6_dst, > + uint8_t cur_hop_limit, uint8_t > mo_flags, > + ovs_be16 router_lt, ovs_be32 > reachable_time, > + ovs_be32 retrans_timer, ovs_be32 > mtu); > +void packet_put_ra_prefix_opt(struct dp_packet *, > + uint8_t plen, uint8_t la_flags, > + ovs_be32 valid_lifetime, ovs_be32 > preferred_lifetime, > + const ovs_be128 router_prefix); > uint32_t packet_csum_pseudoheader(const struct ip_header *); > void IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6); > > -- > 2.9.3 > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev