@@ -1119,6 +1119,39 @@ compose_arp(struct dp_packet *b, uint16_t arp_op,
dp_packet_set_l3(b, arp);
}
+void
+compose_nd(struct dp_packet *b, const struct eth_addr eth_src,
+ struct in6_addr * ipv6_src, struct in6_addr * ipv6_dst)
+{
+ struct in6_addr sn_addr;
+ struct eth_addr eth_dst;
+ struct ovs_nd_msg *ns;
+ struct ovs_nd_opt *nd_opt;
+
+ in6_addr_solicited_node(&sn_addr, ipv6_dst);
+ ipv6_multicast_to_ethernet(ð_dst, &sn_addr);
+
+ dp_packet_init(b, 0);
+ dp_packet_clear(b);
+
+ eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6,
+ IPV6_HEADER_LEN + ICMP6_HEADER_LEN + ND_OPT_LEN);
+ packet_set_ipv6(b, IPPROTO_ICMPV6,
+ ALIGNED_CAST(ovs_be32 *, ipv6_src->s6_addr),
+ ALIGNED_CAST(ovs_be32 *, ipv6_dst->s6_addr),
+ 0, 0, 255);
+
+ ns = dp_packet_l4(b);
+ nd_opt = &ns->options[0];
+
+ ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;
+ ns->icmph.icmp6_code = 0;
+
+ nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
+ packet_set_nd(b, ALIGNED_CAST(ovs_be32 *, ipv6_dst->s6_addr),
+ eth_src, eth_addr_zero);
+}
+
uint32_t
packet_csum_pseudoheader(const struct ip_header *ip)
{
@@ -1025,6 +1025,8 @@ void compose_arp(struct dp_packet *, uint16_t arp_op,
const struct eth_addr arp_sha,
const struct eth_addr arp_tha, bool broadcast,
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 *);
uint32_t packet_csum_pseudoheader(const struct ip_header *);
#endif /* packets.h */
@@ -21,7 +21,6 @@
#include <net/if.h>
#include <sys/socket.h>
#include <netinet/in.h>
-#include <netinet/icmp6.h>
#include "tnl-arp-cache.h"
#include "bfd.h"
@@ -2724,34 +2723,9 @@ tnl_send_nd_request(struct xlate_ctx *ctx, const struct xport *out_dev,
struct in6_addr * ipv6_src, struct in6_addr * ipv6_dst)
{
struct dp_packet packet;
- struct in6_addr sn_addr;
- struct eth_addr eth_dst;
- struct ovs_nd_msg *ns;
- struct ovs_nd_opt *nd_opt;
-
- in6_addr_solicited_node(&sn_addr, ipv6_dst);
- ipv6_multicast_to_ethernet(ð_dst, &sn_addr);
dp_packet_init(&packet, 0);
- dp_packet_clear(&packet);
-
- eth_compose(&packet, eth_dst, eth_src, ETH_TYPE_IPV6,
- IPV6_HEADER_LEN + ICMP6_HEADER_LEN + ND_OPT_LEN);
- packet_set_ipv6(&packet, IPPROTO_ICMPV6,
- ALIGNED_CAST(ovs_be32 *, ipv6_src->s6_addr),
- ALIGNED_CAST(ovs_be32 *, sn_addr.s6_addr),
- 0, 0, 255);
-
- ns = dp_packet_l4(&packet);
- nd_opt = &ns->options[0];
-
- ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;
- ns->icmph.icmp6_code = 0;
-
- nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
- packet_set_nd(&packet, ALIGNED_CAST(ovs_be32 *, ipv6_dst->s6_addr),
- eth_src, eth_addr_zero);
-
+ compose_nd(&packet, eth_src, ipv6_src, ipv6_dst);
compose_table_xlate(ctx, out_dev, &packet);
dp_packet_uninit(&packet);
}