> On Sep 2, 2016, at 10:08 PM, Zongkai LI <zealo...@gmail.com> wrote:
> 
> 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 to compose a basic RA packet, and use
> - packet_put_ra_sll_opt to append a Source Link-layer Address Option to RA
>   packet,
> - packet_put_ra_mtu_opt to append a MTU Option to RA packet,
> - packet_put_ra_prefix_opt to append a Prefix Information Option to a RA
>   packet.
> 
> v1 -> v2
> rebased, separate ovs_nd_opt rename in following patch.

This will need your "signed-off-by".  Also, the version information is helpful, 
but please don't include it as part of the commit comment itself, since we 
won't want to include that in the git history.

> @@ -1419,6 +1420,121 @@ compose_nd_na(struct dp_packet *b,
>                                                       ND_MSG_LEN + 
> ND_OPT_LEN));
> }
> 
> +/* Compose an IPv6 Neighbor Discovery Router Advertisement message without
> + * any IPv6 Neighbor Discovery options. */
> +void
> +compose_nd_ra(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_lifetime,
> +              ovs_be32 reachable_time, ovs_be32 retrans_timer)
> +{
> +    struct ovs_ra_msg *ra;
> +    uint32_t icmp_csum;
> +
> +    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);
> +
> +    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_lifetime;
> +    ra->reachable_time = reachable_time;
> +    ra->retrans_timer = retrans_timer;
> +
> +    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));
> +}
> +
> +/* Append an IPv6 Neighbor Discovery Prefix Information option to a
> + * Router Advertisement message. */

It might be worth noting that the caller is expected to have already called 
compose_nd_ra() on 'b'.

> +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_be32 
> prefix[4])
> +{
> +    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;
> +    packet_update_csum128(b, IPPROTO_ICMPV6, prefix_opt->prefix.be32, 
> prefix);

Is this recalculating the ICMPv6 checksum correctly?  We've added more fields 
than just 'prefix', so I'd think we'd need to include all of those.  Also, I'm 
not sure dp_packet_put_uninit() guarantees that the data will be zeroed-out.  
Regardless, isn't this all unnecessary, since you zero it out and recalculate 
it again later?

> +    memcpy(prefix_opt->prefix.be32, prefix, 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));
> +}
> +
> +/* Append an IPv6 Neighbor Discovery MTU option to a
> + * Router Advertisement message. */

It might be worth noting that the caller is expected to have already called 
compose_nd_ra() on 'b'.

Not a big deal, but I think you can get more of this comment on the first line.

> +void
> +packet_put_ra_mtu_opt(struct dp_packet *b, ovs_be32 mtu)
> +{
> +    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_MTU_OPT_LEN);
> +
> +    struct ovs_ra_msg *ra = dp_packet_l4(b);
> +    struct ovs_nd_mtu_opt *mtu_opt;
> +    uint32_t icmp_csum;
> +
> +    mtu_opt = dp_packet_put_uninit(b, sizeof(struct ovs_nd_mtu_opt));
> +    mtu_opt->type = ND_OPT_MTU;
> +    mtu_opt->len = 1;
> +    mtu_opt->reserved = 0;
> +    ovs_be16 *csum = &(ra->icmph.icmp6_cksum);
> +    *csum = recalc_csum32(*csum, mtu_opt->mtu, mtu);

Same question about checksum here.

> +    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, prev_l4_size + ND_MTU_OPT_LEN));
> +}
> +
> +/* Append an IPv6 Neighbor Discovery Source Link-layer Address option to a
> + * Router Advertisement message. */
> +void
> +packet_put_ra_sll_opt(struct dp_packet *b, const struct eth_addr lla)

It might be worth noting that the caller is expected to have already called 
compose_nd_ra() on 'b'.

> +{
> +    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_OPT_LEN);
> +
> +    struct ovs_ra_msg *ra = dp_packet_l4(b);
> +    struct ovs_nd_opt *lla_opt;
> +    uint32_t icmp_csum;
> +
> +    lla_opt = dp_packet_put_uninit(b, sizeof(struct ovs_nd_opt));
> +    lla_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
> +    lla_opt->nd_opt_len = 1;
> +    ovs_be16 *csum = &(ra->icmph.icmp6_cksum);
> +    *csum = recalc_csum48(*csum, lla_opt->nd_opt_mac, lla);

Same questions about checksum here.

> diff --git a/lib/packets.h b/lib/packets.h
> index dcfcd04..d0e1195 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -841,6 +841,31 @@ 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;      /* Values defined in icmp6.h */

Isn't this value always 3?  I'd probably just use "ND_OPT_PREFIX_INFORMATION".

> +    uint8_t len;

Isn't the length always 4?  I'd just indicate that in the comment.

> +    uint8_t prefix_len;
> +    /* on-link flag, autonomous address-configuration flag, 6-bit reserved. 
> */
> +    uint8_t  la_flags;

Maybe indicate that this uses the "ND_PREFIX_*" flags?

> +    ovs_be32 valid_lifetime;
> +    ovs_be32 preferred_lifetime;
> +    ovs_be32 reserved;
> +    union ovs_16aligned_in6_addr prefix;
> +};
> +BUILD_ASSERT_DECL(ND_PREFIX_OPT_LEN == sizeof(struct ovs_nd_prefix_opt));
> +
> +/* Neighbor Discovery option: MTU. */
> +#define ND_MTU_OPT_LEN 8
> +struct ovs_nd_mtu_opt {
> +    uint8_t  type;      /* Values defined in icmp6.h */

Isn't this value always 5?  I'd probably just use "ND_OPT_MTU".

> +    uint8_t  len;

Isn't the length always 1?  I'd just indicate that in the comment.

> +    ovs_be16 reserved;
> +    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
> @@ -852,9 +877,25 @@ 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 ND_PREFIX_ON_LINK            0x80
> +#define ND_PREFIX_AUTONOMOUS_ADDRESS 0x40

I'd move these under the definition of "ovs_nd_prefix_opt".

> +#define ND_ROUTER_ADV_MANAGED_ADDRESS 0x80
> +#define ND_ROUTER_ADV_OTHER_CONFIG    0x40

I'd move these under the definition of "ovs_ra_msg".  I'd also replace 
"ROUTER_ADV" with "RA", since that's what is used elsewhere in the code.

> +
> +#define RA_MSG_LEN 16
> +struct ovs_ra_msg {
> +    struct icmp6_header icmph;
> +    uint8_t cur_hop_limit;
> +    uint8_t mo_flags;

Maybe indicate that this uses the "ND_RA_*" flags?

Thanks,

--Justin


_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to