@@ -1355,6 +1355,39 @@ compose_nd(struct dp_packet *b, const struct eth_addr eth_src,
ND_MSG_LEN + ND_OPT_LEN));
}
+void
+compose_na(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,
+ ovs_be16 rco_flags)
+{
+ struct ovs_nd_msg *na;
+ struct ovs_nd_opt *nd_opt;
+ uint32_t icmp_csum;
+
+ eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
+ na = compose_ipv6(b, IPPROTO_ICMPV6,
+ ALIGNED_CAST(ovs_be32 *, ipv6_src->s6_addr),
+ ALIGNED_CAST(ovs_be32 *, ipv6_dst->s6_addr),
+ 0, 0, 255,
+ ND_MSG_LEN + ND_OPT_LEN);
+
+ na->icmph.icmp6_type = ND_NEIGHBOR_ADVERT;
+ na->icmph.icmp6_code = 0;
+ na->rco_flags.hi = rco_flags;
+
+ nd_opt = &na->options[0];
+ nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
+ nd_opt->nd_opt_len = 1;
+
+ packet_set_nd(b, ALIGNED_CAST(ovs_be32 *, ipv6_src->s6_addr),
+ eth_addr_zero, eth_src);
+ na->icmph.icmp6_cksum = 0;
+ icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b));
+ na->icmph.icmp6_cksum = csum_finish(csum_continue(icmp_csum, na,
+ ND_MSG_LEN + ND_OPT_LEN));
+}
+
uint32_t
packet_csum_pseudoheader(const struct ip_header *ip)
{
@@ -1069,6 +1069,10 @@ void compose_arp(struct dp_packet *, uint16_t arp_op,
ovs_be32 arp_spa, ovs_be32 arp_tpa);
void compose_nd(struct dp_packet *, const struct eth_addr eth_src,
struct in6_addr *, struct in6_addr *);
+void compose_na(struct dp_packet *,
+ const struct eth_addr eth_src, const struct eth_addr eth_dst,
+ const struct in6_addr *, const struct in6_addr *,
+ ovs_be16 rco_flags);
uint32_t packet_csum_pseudoheader(const struct ip_header *);
void IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6);
Add a method compose_na to compose a NA packet. The ND feature of OVN will base on this. Signed-off-by: Zong Kai LI <zealokii@gmail.com> --- lib/packets.c | 33 +++++++++++++++++++++++++++++++++ lib/packets.h | 4 ++++ 2 files changed, 37 insertions(+)