[ovs-dev] [PATCH v3 1/7] lib: Fix compose nd
Pravin B Shelar
pshelar at ovn.org
Wed Mar 23 21:56:53 UTC 2016
Following patch fixes number of issues with compose nd, like
setting ip packet header, set ICMP opt-len, checksum.
Signed-off-by: Pravin B Shelar <pshelar at ovn.org>
Acked-by: Ben Pfaff <blp at ovn.org>
---
lib/packets.c | 59 +++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 41 insertions(+), 18 deletions(-)
diff --git a/lib/packets.c b/lib/packets.c
index b9a5ba8..d0c0e68 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -794,7 +794,7 @@ eth_compose(struct dp_packet *b, const struct eth_addr eth_dst,
dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + size);
dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
eth = dp_packet_put_uninit(b, ETH_HEADER_LEN);
- data = dp_packet_put_uninit(b, size);
+ data = dp_packet_put_zeros(b, size);
eth->eth_dst = eth_dst;
eth->eth_src = eth_src;
@@ -846,7 +846,6 @@ packet_rh_present(struct dp_packet *packet)
uint8_t *data = dp_packet_l3(packet);
remaining = packet->l4_ofs - packet->l3_ofs;
-
if (remaining < sizeof *nh) {
return false;
}
@@ -1027,9 +1026,7 @@ packet_set_ipv6(struct dp_packet *packet, uint8_t proto, const ovs_be32 src[4],
}
packet_set_ipv6_tc(&nh->ip6_flow, key_tc);
-
packet_set_ipv6_flow_label(&nh->ip6_flow, key_fl);
-
nh->ip6_hlim = key_hl;
}
@@ -1116,7 +1113,8 @@ packet_set_icmp(struct dp_packet *packet, uint8_t type, uint8_t code)
void
packet_set_nd(struct dp_packet *packet, const ovs_be32 target[4],
- const struct eth_addr sll, const struct eth_addr tll) {
+ const struct eth_addr sll, const struct eth_addr tll)
+{
struct ovs_nd_msg *ns;
struct ovs_nd_opt *nd_opt;
int bytes_remain = dp_packet_l4_size(packet);
@@ -1298,34 +1296,60 @@ compose_arp__(struct dp_packet *b)
dp_packet_set_l3(b, arp);
}
+/* This function expect packet with ethernet header with correct
+ * l3 pointer set. */
+static void *
+compose_ipv6(struct dp_packet *packet, uint8_t proto, const ovs_be32 src[4],
+ const ovs_be32 dst[4], uint8_t key_tc, ovs_be32 key_fl,
+ uint8_t key_hl, int size)
+{
+ struct ip6_hdr *nh;
+ void *data;
+
+ nh = dp_packet_l3(packet);
+ nh->ip6_vfc = 0x60;
+ nh->ip6_nxt = proto;
+ nh->ip6_plen = htons(size);
+ data = dp_packet_put_zeros(packet, size);
+ dp_packet_set_l4(packet, data);
+ packet_set_ipv6(packet, proto, src, dst, key_tc, key_fl, key_hl);
+ return data;
+}
+
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 *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;
+ uint32_t icmp_csum;
in6_addr_solicited_node(&sn_addr, ipv6_dst);
ipv6_multicast_to_ethernet(ð_dst, &sn_addr);
- 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 *, sn_addr.s6_addr),
- 0, 0, 255);
-
- ns = dp_packet_l4(b);
- nd_opt = &ns->options[0];
+ eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);
+ ns = compose_ipv6(b, IPPROTO_ICMPV6,
+ ALIGNED_CAST(ovs_be32 *, ipv6_src->s6_addr),
+ ALIGNED_CAST(ovs_be32 *, sn_addr.s6_addr),
+ 0, 0, 255,
+ ND_MSG_LEN + ND_OPT_LEN);
ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;
ns->icmph.icmp6_code = 0;
+ put_16aligned_be32(&ns->rco_flags, htonl(0));
+ nd_opt = &ns->options[0];
nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
+ nd_opt->nd_opt_len = 1;
+
packet_set_nd(b, ALIGNED_CAST(ovs_be32 *, ipv6_dst->s6_addr),
eth_src, eth_addr_zero);
+ ns->icmph.icmp6_cksum = 0;
+ icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b));
+ ns->icmph.icmp6_cksum = csum_finish(csum_continue(icmp_csum, ns,
+ ND_MSG_LEN + ND_OPT_LEN));
}
uint32_t
@@ -1352,15 +1376,14 @@ packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *ip6)
partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_src.be32[1])));
partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_src.be32[2])));
partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_src.be32[3])));
+
partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_dst.be32[0])));
partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_dst.be32[1])));
partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_dst.be32[2])));
partial = csum_add32(partial, get_16aligned_be32(&(ip6->ip6_dst.be32[3])));
- partial = csum_add16(partial, 0);
+ partial = csum_add16(partial, htons(ip6->ip6_nxt));
partial = csum_add16(partial, ip6->ip6_plen);
- partial = csum_add16(partial, 0);
- partial = csum_add16(partial, ip6->ip6_nxt);
return partial;
}
--
1.8.3.1
More information about the dev
mailing list