mirror of
https://github.com/openvswitch/ovs
synced 2025-10-25 15:07:05 +00:00
lib/flow: Add IPv6 support for flow_compose().
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 <jrajahalme@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
125
lib/flow.c
125
lib/flow.c
@@ -1058,6 +1058,78 @@ flow_set_mpls_bos(struct flow *flow, uint8_t bos)
|
|||||||
set_mpls_lse_bos(&flow->mpls_lse, bos);
|
set_mpls_lse_bos(&flow->mpls_lse, bos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
flow_compose_l4(struct ofpbuf *b, const struct flow *flow)
|
||||||
|
{
|
||||||
|
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_ICMP) {
|
||||||
|
struct icmp_header *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);
|
||||||
|
} 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Puts into 'b' a packet that flow_extract() would parse as having the given
|
/* Puts into 'b' a packet that flow_extract() would parse as having the given
|
||||||
* 'flow'.
|
* 'flow'.
|
||||||
*
|
*
|
||||||
@@ -1067,6 +1139,7 @@ flow_set_mpls_bos(struct flow *flow, uint8_t bos)
|
|||||||
void
|
void
|
||||||
flow_compose(struct ofpbuf *b, const struct flow *flow)
|
flow_compose(struct ofpbuf *b, const struct flow *flow)
|
||||||
{
|
{
|
||||||
|
/* eth_compose() sets l3 pointer and makes sure it is 32-bit aligned. */
|
||||||
eth_compose(b, flow->dl_dst, flow->dl_src, ntohs(flow->dl_type), 0);
|
eth_compose(b, flow->dl_dst, flow->dl_src, ntohs(flow->dl_type), 0);
|
||||||
if (flow->dl_type == htons(FLOW_DL_TYPE_NONE)) {
|
if (flow->dl_type == htons(FLOW_DL_TYPE_NONE)) {
|
||||||
struct eth_header *eth = b->l2;
|
struct eth_header *eth = b->l2;
|
||||||
@@ -1081,7 +1154,7 @@ flow_compose(struct ofpbuf *b, const struct flow *flow)
|
|||||||
if (flow->dl_type == htons(ETH_TYPE_IP)) {
|
if (flow->dl_type == htons(ETH_TYPE_IP)) {
|
||||||
struct ip_header *ip;
|
struct ip_header *ip;
|
||||||
|
|
||||||
b->l3 = ip = ofpbuf_put_zeros(b, sizeof *ip);
|
ip = ofpbuf_put_zeros(b, sizeof *ip);
|
||||||
ip->ip_ihl_ver = IP_IHL_VER(5, 4);
|
ip->ip_ihl_ver = IP_IHL_VER(5, 4);
|
||||||
ip->ip_tos = flow->nw_tos;
|
ip->ip_tos = flow->nw_tos;
|
||||||
ip->ip_ttl = flow->nw_ttl;
|
ip->ip_ttl = flow->nw_ttl;
|
||||||
@@ -1095,44 +1168,32 @@ flow_compose(struct ofpbuf *b, const struct flow *flow)
|
|||||||
ip->ip_frag_off |= htons(100);
|
ip->ip_frag_off |= htons(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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);
|
b->l4 = ofpbuf_tail(b);
|
||||||
tcp->tcp_src = flow->tp_src;
|
|
||||||
tcp->tcp_dst = flow->tp_dst;
|
|
||||||
tcp->tcp_ctl = TCP_CTL(ntohs(flow->tcp_flags), 5);
|
|
||||||
} else if (flow->nw_proto == IPPROTO_UDP) {
|
|
||||||
struct udp_header *udp;
|
|
||||||
|
|
||||||
b->l4 = udp = ofpbuf_put_zeros(b, sizeof *udp);
|
flow_compose_l4(b, flow);
|
||||||
udp->udp_src = flow->tp_src;
|
|
||||||
udp->udp_dst = flow->tp_dst;
|
|
||||||
} else if (flow->nw_proto == IPPROTO_SCTP) {
|
|
||||||
struct sctp_header *sctp;
|
|
||||||
|
|
||||||
b->l4 = sctp = ofpbuf_put_zeros(b, sizeof *sctp);
|
|
||||||
sctp->sctp_src = flow->tp_src;
|
|
||||||
sctp->sctp_dst = flow->tp_dst;
|
|
||||||
} else if (flow->nw_proto == IPPROTO_ICMP) {
|
|
||||||
struct icmp_header *icmp;
|
|
||||||
|
|
||||||
b->l4 = 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ip = b->l3;
|
|
||||||
ip->ip_tot_len = htons((uint8_t *) b->data + b->size
|
ip->ip_tot_len = htons((uint8_t *) b->data + b->size
|
||||||
- (uint8_t *) b->l3);
|
- (uint8_t *) b->l3);
|
||||||
ip->ip_csum = csum(ip, sizeof *ip);
|
ip->ip_csum = csum(ip, sizeof *ip);
|
||||||
} else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
|
} else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
|
||||||
/* XXX */
|
struct ovs_16aligned_ip6_hdr *nh;
|
||||||
|
|
||||||
|
nh = ofpbuf_put_zeros(b, sizeof *nh);
|
||||||
|
put_16aligned_be32(&nh->ip6_flow, htonl(6 << 28) |
|
||||||
|
htonl(flow->nw_tos << 20) | 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);
|
||||||
|
|
||||||
|
flow_compose_l4(b, flow);
|
||||||
|
|
||||||
|
nh->ip6_plen =
|
||||||
|
b->l7 ? htons((uint8_t *) b->l7 - (uint8_t *) b->l4) : htons(0);
|
||||||
} else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
|
} else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
|
||||||
flow->dl_type == htons(ETH_TYPE_RARP)) {
|
flow->dl_type == htons(ETH_TYPE_RARP)) {
|
||||||
struct arp_eth_header *arp;
|
struct arp_eth_header *arp;
|
||||||
|
|||||||
@@ -689,13 +689,13 @@ ovs-appctl -t ovs-ofctl exit
|
|||||||
|
|
||||||
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
|
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)
|
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
|
dnl
|
||||||
NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
|
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
|
dnl
|
||||||
NXT_PACKET_IN (xid=0x0): cookie=0xc total_len=64 in_port=1 (via action) data_len=64 (unbuffered)
|
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
|
pkt_len=64
|
||||||
stripped=4
|
stripped=4
|
||||||
hdr_len=60
|
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/ /\
|
AT_CHECK([[sort sflow.log | $EGREP 'IFCOUNTERS|ERROR' | head -6 | sed 's/ /\
|
||||||
@@ -1961,7 +1961,7 @@ IFCOUNTERS
|
|||||||
ifspeed=100000000
|
ifspeed=100000000
|
||||||
direction=0
|
direction=0
|
||||||
status=0
|
status=0
|
||||||
in_octets=98
|
in_octets=138
|
||||||
in_unicasts=3
|
in_unicasts=3
|
||||||
in_multicasts=0
|
in_multicasts=0
|
||||||
in_broadcasts=4294967295
|
in_broadcasts=4294967295
|
||||||
@@ -2030,7 +2030,7 @@ IFCOUNTERS
|
|||||||
ifspeed=100000000
|
ifspeed=100000000
|
||||||
direction=0
|
direction=0
|
||||||
status=0
|
status=0
|
||||||
in_octets=98
|
in_octets=138
|
||||||
in_unicasts=3
|
in_unicasts=3
|
||||||
in_multicasts=0
|
in_multicasts=0
|
||||||
in_broadcasts=4294967295
|
in_broadcasts=4294967295
|
||||||
|
|||||||
Reference in New Issue
Block a user