Add the missing code for generating IPv6 packets for testing purposes. Also make flow_compose() set the l4 and l7 pointers more consistently with flow_extract().
Signed-off-by: Jarno Rajahalme <[email protected]> --- lib/flow.c | 94 +++++++++++++++++++++++++++++++++++++++++++++---- lib/packets.c | 4 +-- lib/packets.h | 2 ++ tests/ofproto-dpif.at | 12 +++---- 4 files changed, 97 insertions(+), 15 deletions(-) diff --git a/lib/flow.c b/lib/flow.c index c6683a5..3f2fb19 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -1077,44 +1077,124 @@ flow_compose(struct ofpbuf *b, const struct flow *flow) ip->ip_frag_off |= htons(100); } } + + b->l4 = ofpbuf_tail(b); + if (!(flow->nw_frag & FLOW_NW_FRAG_ANY) || !(flow->nw_frag & FLOW_NW_FRAG_LATER)) { if (flow->nw_proto == IPPROTO_TCP) { struct tcp_header *tcp; - b->l4 = tcp = ofpbuf_put_zeros(b, sizeof *tcp); + tcp = ofpbuf_put_zeros(b, sizeof *tcp); tcp->tcp_src = flow->tp_src; tcp->tcp_dst = flow->tp_dst; tcp->tcp_ctl = TCP_CTL(ntohs(flow->tcp_flags), 5); + b->l7 = ofpbuf_tail(b); } else if (flow->nw_proto == IPPROTO_UDP) { struct udp_header *udp; - b->l4 = udp = ofpbuf_put_zeros(b, sizeof *udp); + udp = ofpbuf_put_zeros(b, sizeof *udp); udp->udp_src = flow->tp_src; udp->udp_dst = flow->tp_dst; + b->l7 = ofpbuf_tail(b); } else if (flow->nw_proto == IPPROTO_SCTP) { struct sctp_header *sctp; - b->l4 = sctp = ofpbuf_put_zeros(b, sizeof *sctp); + sctp = ofpbuf_put_zeros(b, sizeof *sctp); sctp->sctp_src = flow->tp_src; sctp->sctp_dst = flow->tp_dst; + b->l7 = ofpbuf_tail(b); } else if (flow->nw_proto == IPPROTO_ICMP) { struct icmp_header *icmp; - b->l4 = icmp = ofpbuf_put_zeros(b, sizeof *icmp); + icmp = ofpbuf_put_zeros(b, sizeof *icmp); icmp->icmp_type = ntohs(flow->tp_src); icmp->icmp_code = ntohs(flow->tp_dst); icmp->icmp_csum = csum(icmp, ICMP_HEADER_LEN); + b->l7 = ofpbuf_tail(b); } - b->l7 = ofpbuf_tail(b); } - ip = b->l3; ip->ip_tot_len = htons((uint8_t *) b->data + b->size - (uint8_t *) b->l3); ip->ip_csum = csum(ip, sizeof *ip); } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { - /* XXX */ + struct ovs_16aligned_ip6_hdr *nh; + + b->l3 = nh = ofpbuf_put_zeros(b, sizeof *nh); + nh->ip6_vfc = IP_IHL_VER(0, 6); + packet_set_ipv6_tc(&nh->ip6_flow, flow->nw_tos); + packet_set_ipv6_flow_label(&nh->ip6_flow, flow->ipv6_label); + nh->ip6_hlim = flow->nw_ttl; + nh->ip6_nxt = flow->nw_proto; + + memcpy(&nh->ip6_src, &flow->ipv6_src, sizeof(nh->ip6_src)); + memcpy(&nh->ip6_dst, &flow->ipv6_dst, sizeof(nh->ip6_dst)); + + b->l4 = ofpbuf_tail(b); + + if (!(flow->nw_frag & FLOW_NW_FRAG_ANY) + || !(flow->nw_frag & FLOW_NW_FRAG_LATER)) { + if (flow->nw_proto == IPPROTO_TCP) { + struct tcp_header *tcp; + + tcp = ofpbuf_put_zeros(b, sizeof *tcp); + tcp->tcp_src = flow->tp_src; + tcp->tcp_dst = flow->tp_dst; + tcp->tcp_ctl = TCP_CTL(ntohs(flow->tcp_flags), 5); + b->l7 = ofpbuf_tail(b); + } else if (flow->nw_proto == IPPROTO_UDP) { + struct udp_header *udp; + + udp = ofpbuf_put_zeros(b, sizeof *udp); + udp->udp_src = flow->tp_src; + udp->udp_dst = flow->tp_dst; + b->l7 = ofpbuf_tail(b); + } else if (flow->nw_proto == IPPROTO_SCTP) { + struct sctp_header *sctp; + + sctp = ofpbuf_put_zeros(b, sizeof *sctp); + sctp->sctp_src = flow->tp_src; + sctp->sctp_dst = flow->tp_dst; + b->l7 = ofpbuf_tail(b); + } else if (flow->nw_proto == IPPROTO_ICMPV6) { + struct icmp6_hdr *icmp; + + icmp = ofpbuf_put_zeros(b, sizeof *icmp); + icmp->icmp6_type = ntohs(flow->tp_src); + icmp->icmp6_code = ntohs(flow->tp_dst); + + if (icmp->icmp6_code == 0 && + (icmp->icmp6_type == ND_NEIGHBOR_SOLICIT || + icmp->icmp6_type == ND_NEIGHBOR_ADVERT)) { + struct in6_addr *nd_target; + struct nd_opt_hdr *nd_opt; + + nd_target = ofpbuf_put_zeros(b, sizeof *nd_target); + *nd_target = flow->nd_target; + + if (!eth_addr_is_zero(flow->arp_sha)) { + nd_opt = ofpbuf_put_zeros(b, 8); + nd_opt->nd_opt_len = 1; + nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; + memcpy(nd_opt + 1, flow->arp_sha, ETH_ADDR_LEN); + } + if (!eth_addr_is_zero(flow->arp_tha)) { + nd_opt = ofpbuf_put_zeros(b, 8); + nd_opt->nd_opt_len = 1; + nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; + memcpy(nd_opt + 1, flow->arp_tha, ETH_ADDR_LEN); + } + } + icmp->icmp6_cksum = (OVS_FORCE uint16_t) + csum(icmp, (char *)ofpbuf_tail(b) - (char *)icmp); + b->l7 = ofpbuf_tail(b); + } + } + + nh->ip6_plen = b->l7 + ? htons((uint8_t *) b->l7 - (uint8_t *) b->l4) + : CONSTANT_HTONS(0); } else if (flow->dl_type == htons(ETH_TYPE_ARP) || flow->dl_type == htons(ETH_TYPE_RARP)) { struct arp_eth_header *arp; diff --git a/lib/packets.c b/lib/packets.c index 4bec4d1..5349d41 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -752,7 +752,7 @@ packet_set_ipv6_addr(struct ofpbuf *packet, uint8_t proto, memcpy(addr, new_addr, sizeof(*addr)); } -static void +void packet_set_ipv6_flow_label(ovs_16aligned_be32 *flow_label, ovs_be32 flow_key) { ovs_be32 old_label = get_16aligned_be32(flow_label); @@ -760,7 +760,7 @@ packet_set_ipv6_flow_label(ovs_16aligned_be32 *flow_label, ovs_be32 flow_key) put_16aligned_be32(flow_label, new_label); } -static void +void packet_set_ipv6_tc(ovs_16aligned_be32 *flow_label, uint8_t tc) { ovs_be32 old_label = get_16aligned_be32(flow_label); diff --git a/lib/packets.h b/lib/packets.h index ef8c00c..a1e1859 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -637,6 +637,8 @@ void packet_set_ipv4(struct ofpbuf *, ovs_be32 src, ovs_be32 dst, uint8_t tos, void packet_set_ipv6(struct ofpbuf *, uint8_t proto, const ovs_be32 src[4], const ovs_be32 dst[4], uint8_t tc, ovs_be32 fl, uint8_t hlmit); +void packet_set_ipv6_tc(ovs_16aligned_be32 *, uint8_t tc); +void packet_set_ipv6_flow_label(ovs_16aligned_be32 *, ovs_be32 flow_key); void packet_set_tcp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst); void packet_set_udp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst); void packet_set_sctp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst); diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index b78e156..e817061 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -689,13 +689,13 @@ ovs-appctl -t ovs-ofctl exit AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=64 in_port=1 (via action) data_len=64 (unbuffered) -mplsm,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1 +mplsm,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=128,mpls_bos=1 dnl NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=64 in_port=1 (via action) data_len=64 (unbuffered) -mplsm,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1 +mplsm,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=128,mpls_bos=1 dnl NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=64 in_port=1 (via action) data_len=64 (unbuffered) -mplsm,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=64,mpls_bos=1 +mplsm,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=70:77:77:77:77:77,dl_dst=50:54:00:00:00:07,mpls_label=1000,mpls_tc=7,mpls_ttl=128,mpls_bos=1 ]) @@ -1924,7 +1924,7 @@ HEADER pkt_len=64 stripped=4 hdr_len=60 - hdr=50-54-00-00-00-05-50-54-00-00-00-07-86-DD-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + hdr=50-54-00-00-00-05-50-54-00-00-00-07-86-DD-67-00-00-00-00-00-0A-80-FE-80-00-00-00-00-00-00-00-00-00-00-00-00-00-01-FE-80-00-00-00-00-00-00-00-00-00-00-00-00-00-02-00-00-00-00-00-00 ]) AT_CHECK([[sort sflow.log | $EGREP 'IFCOUNTERS|ERROR' | head -6 | sed 's/ /\ @@ -1961,7 +1961,7 @@ IFCOUNTERS ifspeed=100000000 direction=0 status=0 - in_octets=98 + in_octets=138 in_unicasts=3 in_multicasts=0 in_broadcasts=4294967295 @@ -2030,7 +2030,7 @@ IFCOUNTERS ifspeed=100000000 direction=0 status=0 - in_octets=98 + in_octets=138 in_unicasts=3 in_multicasts=0 in_broadcasts=4294967295 -- 1.7.10.4 _______________________________________________ dev mailing list [email protected] http://openvswitch.org/mailman/listinfo/dev
