From dc235f7fbcff39b318b715f9d3d01f97b2634357 Mon Sep 17 00:00:00 2001 From: Jarno Rajahalme Date: Mon, 28 Oct 2013 13:54:40 -0700 Subject: [PATCH] TCP flags matching support. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit tcp_flags=flags/mask Bitwise match on TCP flags. The flags and mask are 16-bit num‐ bers written in decimal or in hexadecimal prefixed by 0x. Each 1-bit in mask requires that the corresponding bit in port must match. Each 0-bit in mask causes the corresponding bit to be ignored. TCP protocol currently defines 9 flag bits, and additional 3 bits are reserved (must be transmitted as zero), see RFCs 793, 3168, and 3540. The flag bits are, numbering from the least significant bit: 0: FIN No more data from sender. 1: SYN Synchronize sequence numbers. 2: RST Reset the connection. 3: PSH Push function. 4: ACK Acknowledgement field significant. 5: URG Urgent pointer field significant. 6: ECE ECN Echo. 7: CWR Congestion Windows Reduced. 8: NS Nonce Sum. 9-11: Reserved. 12-15: Not matchable, must be zero. Signed-off-by: Jarno Rajahalme Signed-off-by: Ben Pfaff Acked-by: Jesse Gross --- datapath/flow.c | 2 + datapath/flow.h | 2 + datapath/flow_netlink.c | 31 ++++++++++++++- include/linux/openvswitch.h | 1 + include/openflow/nicira-ext.h | 12 ++++++ lib/flow.c | 5 ++- lib/flow.h | 7 ++-- lib/match.c | 26 ++++++++++++- lib/match.h | 2 + lib/meta-flow.c | 40 +++++++++++++++++++ lib/meta-flow.h | 2 + lib/nx-match.c | 4 +- lib/odp-execute.c | 1 + lib/odp-util.c | 36 +++++++++++++++++ lib/ofp-util.c | 2 +- ofproto/ofproto-dpif-xlate.c | 2 +- tests/ofp-print.at | 26 ++++++------- tests/ofproto-dpif.at | 62 ++++++++++++++--------------- tests/ovs-ofctl.at | 73 +++++++++++++++++++++++++++++++++++ utilities/ovs-ofctl.8.in | 34 ++++++++++++++++ 20 files changed, 315 insertions(+), 55 deletions(-) diff --git a/datapath/flow.c b/datapath/flow.c index 510bb8785..57eb6b565 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -482,6 +482,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key) struct tcphdr *tcp = tcp_hdr(skb); key->ipv4.tp.src = tcp->source; key->ipv4.tp.dst = tcp->dest; + key->ipv4.tp.flags = TCP_FLAGS_BE16(tcp); } } else if (key->ip.proto == IPPROTO_UDP) { if (udphdr_ok(skb)) { @@ -550,6 +551,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key) struct tcphdr *tcp = tcp_hdr(skb); key->ipv6.tp.src = tcp->source; key->ipv6.tp.dst = tcp->dest; + key->ipv6.tp.flags = TCP_FLAGS_BE16(tcp); } } else if (key->ip.proto == NEXTHDR_UDP) { if (udphdr_ok(skb)) { diff --git a/datapath/flow.h b/datapath/flow.h index bd2df7d82..fdc309fe1 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -96,6 +96,7 @@ struct sw_flow_key { struct { __be16 src; /* TCP/UDP/SCTP source port. */ __be16 dst; /* TCP/UDP/SCTP destination port. */ + __be16 flags; /* TCP flags. */ } tp; struct { u8 sha[ETH_ALEN]; /* ARP source hardware address. */ @@ -112,6 +113,7 @@ struct sw_flow_key { struct { __be16 src; /* TCP/UDP/SCTP source port. */ __be16 dst; /* TCP/UDP/SCTP destination port. */ + __be16 flags; /* TCP flags. */ } tp; struct { struct in6_addr target; /* ND target address. */ diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c index 515a9f61e..75c72b361 100644 --- a/datapath/flow_netlink.c +++ b/datapath/flow_netlink.c @@ -114,6 +114,7 @@ static bool match_validate(const struct sw_flow_match *match, mask_allowed &= ~((1ULL << OVS_KEY_ATTR_IPV4) | (1ULL << OVS_KEY_ATTR_IPV6) | (1ULL << OVS_KEY_ATTR_TCP) + | (1ULL << OVS_KEY_ATTR_TCP_FLAGS) | (1ULL << OVS_KEY_ATTR_UDP) | (1ULL << OVS_KEY_ATTR_SCTP) | (1ULL << OVS_KEY_ATTR_ICMP) @@ -154,8 +155,11 @@ static bool match_validate(const struct sw_flow_match *match, if (match->key->ip.proto == IPPROTO_TCP) { key_expected |= 1ULL << OVS_KEY_ATTR_TCP; - if (match->mask && (match->mask->key.ip.proto == 0xff)) + key_expected |= 1ULL << OVS_KEY_ATTR_TCP_FLAGS; + if (match->mask && (match->mask->key.ip.proto == 0xff)) { mask_allowed |= 1ULL << OVS_KEY_ATTR_TCP; + mask_allowed |= 1ULL << OVS_KEY_ATTR_TCP_FLAGS; + } } if (match->key->ip.proto == IPPROTO_ICMP) { @@ -186,8 +190,11 @@ static bool match_validate(const struct sw_flow_match *match, if (match->key->ip.proto == IPPROTO_TCP) { key_expected |= 1ULL << OVS_KEY_ATTR_TCP; - if (match->mask && (match->mask->key.ip.proto == 0xff)) + key_expected |= 1ULL << OVS_KEY_ATTR_TCP_FLAGS; + if (match->mask && (match->mask->key.ip.proto == 0xff)) { mask_allowed |= 1ULL << OVS_KEY_ATTR_TCP; + mask_allowed |= 1ULL << OVS_KEY_ATTR_TCP_FLAGS; + } } if (match->key->ip.proto == IPPROTO_ICMPV6) { @@ -235,6 +242,7 @@ static const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = { [OVS_KEY_ATTR_IPV4] = sizeof(struct ovs_key_ipv4), [OVS_KEY_ATTR_IPV6] = sizeof(struct ovs_key_ipv6), [OVS_KEY_ATTR_TCP] = sizeof(struct ovs_key_tcp), + [OVS_KEY_ATTR_TCP_FLAGS] = sizeof(__be16), [OVS_KEY_ATTR_UDP] = sizeof(struct ovs_key_udp), [OVS_KEY_ATTR_SCTP] = sizeof(struct ovs_key_sctp), [OVS_KEY_ATTR_ICMP] = sizeof(struct ovs_key_icmp), @@ -634,6 +642,19 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs, attrs &= ~(1ULL << OVS_KEY_ATTR_TCP); } + if (attrs & (1ULL << OVS_KEY_ATTR_TCP_FLAGS)) { + if (orig_attrs & (1ULL << OVS_KEY_ATTR_IPV4)) { + SW_FLOW_KEY_PUT(match, ipv4.tp.flags, + nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]), + is_mask); + } else { + SW_FLOW_KEY_PUT(match, ipv6.tp.flags, + nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]), + is_mask); + } + attrs &= ~(1ULL << OVS_KEY_ATTR_TCP_FLAGS); + } + if (attrs & (1ULL << OVS_KEY_ATTR_UDP)) { const struct ovs_key_udp *udp_key; @@ -1004,9 +1025,15 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey, if (swkey->eth.type == htons(ETH_P_IP)) { tcp_key->tcp_src = output->ipv4.tp.src; tcp_key->tcp_dst = output->ipv4.tp.dst; + if (nla_put_be16(skb, OVS_KEY_ATTR_TCP_FLAGS, + output->ipv4.tp.flags)) + goto nla_put_failure; } else if (swkey->eth.type == htons(ETH_P_IPV6)) { tcp_key->tcp_src = output->ipv6.tp.src; tcp_key->tcp_dst = output->ipv6.tp.dst; + if (nla_put_be16(skb, OVS_KEY_ATTR_TCP_FLAGS, + output->ipv6.tp.flags)) + goto nla_put_failure; } } else if (swkey->ip.proto == IPPROTO_UDP) { struct ovs_key_udp *udp_key; diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h index f46d9d033..b429201cc 100644 --- a/include/linux/openvswitch.h +++ b/include/linux/openvswitch.h @@ -294,6 +294,7 @@ enum ovs_key_attr { OVS_KEY_ATTR_SKB_MARK, /* u32 skb mark */ OVS_KEY_ATTR_TUNNEL, /* Nested set of ovs_tunnel attributes */ OVS_KEY_ATTR_SCTP, /* struct ovs_key_sctp */ + OVS_KEY_ATTR_TCP_FLAGS, /* be16 TCP flags. */ #ifdef __KERNEL__ OVS_KEY_ATTR_IPV4_TUNNEL, /* struct ovs_key_ipv4_tunnel */ diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h index 3362a4919..a8845a82a 100644 --- a/include/openflow/nicira-ext.h +++ b/include/openflow/nicira-ext.h @@ -1784,6 +1784,18 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24); #define NXM_NX_PKT_MARK NXM_HEADER (0x0001, 33, 4) #define NXM_NX_PKT_MARK_W NXM_HEADER_W(0x0001, 33, 4) +/* The flags in the TCP header. +* +* Prereqs: +* NXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd. +* NXM_OF_IP_PROTO must match 6 exactly. +* +* Format: 16-bit integer with 4 most-significant bits forced to 0. +* +* Masking: Bits 0-11 fully maskable. */ +#define NXM_NX_TCP_FLAGS NXM_HEADER (0x0001, 34, 2) +#define NXM_NX_TCP_FLAGS_W NXM_HEADER_W(0x0001, 34, 2) + /* ## --------------------- ## */ /* ## Requests and replies. ## */ /* ## --------------------- ## */ diff --git a/lib/flow.c b/lib/flow.c index 51851cfdb..31fd07cba 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -256,6 +256,7 @@ parse_tcp(struct ofpbuf *packet, struct ofpbuf *b, struct flow *flow) if (tcp) { flow->tp_src = tcp->tcp_src; flow->tp_dst = tcp->tcp_dst; + flow->tcp_flags = tcp->tcp_ctl & htons(0x0fff); packet->l7 = b->data; } } @@ -514,7 +515,7 @@ flow_zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards) void flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd) { - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 21); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 22); fmd->tun_id = flow->tunnel.tun_id; fmd->tun_src = flow->tunnel.ip_src; @@ -1044,7 +1045,7 @@ flow_compose(struct ofpbuf *b, const struct flow *flow) b->l4 = tcp = ofpbuf_put_zeros(b, sizeof *tcp); tcp->tcp_src = flow->tp_src; tcp->tcp_dst = flow->tp_dst; - tcp->tcp_ctl = TCP_CTL(0, 5); + tcp->tcp_ctl = TCP_CTL(ntohs(flow->tcp_flags), 5); } else if (flow->nw_proto == IPPROTO_UDP) { struct udp_header *udp; diff --git a/lib/flow.h b/lib/flow.h index ad5149690..093d509bc 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -37,7 +37,7 @@ struct ofpbuf; /* This sequence number should be incremented whenever anything involving flows * or the wildcarding of flows changes. This will cause build assertion * failures in places which likely need to be updated. */ -#define FLOW_WC_SEQ 21 +#define FLOW_WC_SEQ 22 #define FLOW_N_REGS 8 BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS); @@ -107,6 +107,7 @@ struct flow { ovs_be16 dl_type; /* Ethernet frame type. */ ovs_be16 tp_src; /* TCP/UDP/SCTP source port. */ ovs_be16 tp_dst; /* TCP/UDP/SCTP destination port. */ + ovs_be16 tcp_flags; /* TCP flags. */ uint8_t dl_src[6]; /* Ethernet source address. */ uint8_t dl_dst[6]; /* Ethernet destination address. */ uint8_t nw_proto; /* IP protocol or low 8 bits of ARP opcode. */ @@ -123,8 +124,8 @@ BUILD_ASSERT_DECL(sizeof(struct flow) % 4 == 0); /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */ BUILD_ASSERT_DECL(offsetof(struct flow, nw_frag) + 1 - == sizeof(struct flow_tnl) + 152 - && FLOW_WC_SEQ == 21); + == sizeof(struct flow_tnl) + 154 + && FLOW_WC_SEQ == 22); /* Represents the metadata fields of struct flow. */ struct flow_metadata { diff --git a/lib/match.c b/lib/match.c index 73b1bf0fa..0f674b09c 100644 --- a/lib/match.c +++ b/lib/match.c @@ -122,6 +122,9 @@ match_wc_init(struct match *match, const struct flow *flow) memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src); memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst); } + if (flow->nw_proto == IPPROTO_TCP) { + memset(&wc->masks.tcp_flags, 0xff, sizeof wc->masks.tcp_flags); + } if (flow->nw_proto == IPPROTO_ICMPV6) { memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha); @@ -532,6 +535,19 @@ match_set_tp_dst_masked(struct match *match, ovs_be16 port, ovs_be16 mask) match->wc.masks.tp_dst = mask; } +void +match_set_tcp_flags(struct match *match, ovs_be16 flags) +{ + match_set_tcp_flags_masked(match, flags, OVS_BE16_MAX); +} + +void +match_set_tcp_flags_masked(struct match *match, ovs_be16 flags, ovs_be16 mask) +{ + match->flow.tcp_flags = flags & mask; + match->wc.masks.tcp_flags = mask; +} + void match_set_nw_proto(struct match *match, uint8_t nw_proto) { @@ -826,7 +842,7 @@ match_format(const struct match *match, struct ds *s, unsigned int priority) int i; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 21); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 22); if (priority != OFP_DEFAULT_PRIORITY) { ds_put_format(s, "priority=%u,", priority); @@ -1052,6 +1068,14 @@ match_format(const struct match *match, struct ds *s, unsigned int priority) format_be16_masked(s, "tp_src", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "tp_dst", f->tp_dst, wc->masks.tp_dst); } + if (is_ip_any(f) && f->nw_proto == IPPROTO_TCP && wc->masks.tcp_flags) { + if (wc->masks.tcp_flags == htons(UINT16_MAX)) { + ds_put_format(s, "tcp_flags=0x%03"PRIx16",", ntohs(f->tcp_flags)); + } else { + ds_put_format(s, "tcp_flags=0x%03"PRIx16"/0x%03"PRIx16",", + ntohs(f->tcp_flags), ntohs(wc->masks.tcp_flags)); + } + } if (s->length > start_len && ds_last(s) == ',') { s->length--; diff --git a/lib/match.h b/lib/match.h index 6e87a096d..1e938a18e 100644 --- a/lib/match.h +++ b/lib/match.h @@ -88,6 +88,8 @@ void match_set_tp_src(struct match *, ovs_be16); void match_set_tp_src_masked(struct match *, ovs_be16 port, ovs_be16 mask); void match_set_tp_dst(struct match *, ovs_be16); void match_set_tp_dst_masked(struct match *, ovs_be16 port, ovs_be16 mask); +void match_set_tcp_flags(struct match *, ovs_be16); +void match_set_tcp_flags_masked(struct match *, ovs_be16 flags, ovs_be16 mask); void match_set_nw_proto(struct match *, uint8_t); void match_set_nw_src(struct match *, ovs_be32); void match_set_nw_src_masked(struct match *, ovs_be32 ip, ovs_be32 mask); diff --git a/lib/meta-flow.c b/lib/meta-flow.c index 12811ef07..b9553af0d 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -559,6 +559,17 @@ static const struct mf_field mf_fields[MFF_N_IDS] = { OXM_OF_TCP_DST, "OXM_OF_TCP_DST", OFPUTIL_P_ANY, OFPUTIL_P_NXM_OXM_ANY, + }, { + MFF_TCP_FLAGS, "tcp_flags", NULL, + 2, 12, + MFM_FULLY, + MFS_HEXADECIMAL, + MFP_TCP, + false, + NXM_NX_TCP_FLAGS, "NXM_NX_TCP_FLAGS", + NXM_NX_TCP_FLAGS, "NXM_NX_TCP_FLAGS", + OFPUTIL_P_NXM_OXM_ANY, + OFPUTIL_P_NXM_OXM_ANY, }, { @@ -919,6 +930,8 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc) case MFF_ICMPV4_CODE: case MFF_ICMPV6_CODE: return !wc->masks.tp_dst; + case MFF_TCP_FLAGS: + return !wc->masks.tcp_flags; case MFF_N_IDS: default: @@ -1128,6 +1141,8 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value) return !(value->u8 & ~IP_ECN_MASK); case MFF_IP_FRAG: return !(value->u8 & ~FLOW_NW_FRAG_MASK); + case MFF_TCP_FLAGS: + return !(value->be16 & ~htons(0x0fff)); case MFF_ARP_OP: return !(value->be16 & htons(0xff00)); @@ -1326,6 +1341,10 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow, value->be16 = flow->tp_dst; break; + case MFF_TCP_FLAGS: + value->be16 = flow->tcp_flags; + break; + case MFF_ICMPV4_TYPE: case MFF_ICMPV6_TYPE: value->u8 = ntohs(flow->tp_src); @@ -1518,6 +1537,10 @@ mf_set_value(const struct mf_field *mf, match_set_tp_dst(match, value->be16); break; + case MFF_TCP_FLAGS: + match_set_tcp_flags(match, value->be16); + break; + case MFF_ICMPV4_TYPE: case MFF_ICMPV6_TYPE: match_set_icmp_type(match, value->u8); @@ -1730,6 +1753,10 @@ mf_set_flow_value(const struct mf_field *mf, flow->tp_dst = value->be16; break; + case MFF_TCP_FLAGS: + flow->tcp_flags = value->be16; + break; + case MFF_ICMPV4_TYPE: case MFF_ICMPV6_TYPE: flow->tp_src = htons(value->u8); @@ -1941,6 +1968,11 @@ mf_set_wild(const struct mf_field *mf, struct match *match) match->flow.tp_dst = htons(0); break; + case MFF_TCP_FLAGS: + match->wc.masks.tcp_flags = htons(0); + match->flow.tcp_flags = htons(0); + break; + case MFF_ND_TARGET: memset(&match->wc.masks.nd_target, 0, sizeof match->wc.masks.nd_target); @@ -2111,6 +2143,10 @@ mf_set(const struct mf_field *mf, match_set_tp_dst_masked(match, value->be16, mask->be16); break; + case MFF_TCP_FLAGS: + match_set_tcp_flags_masked(match, value->be16, mask->be16); + break; + case MFF_N_IDS: default: NOT_REACHED(); @@ -2232,6 +2268,10 @@ mf_random_value(const struct mf_field *mf, union mf_value *value) case MFF_ND_TLL: break; + case MFF_TCP_FLAGS: + value->be16 &= htons(0x0fff); + break; + case MFF_IN_PORT_OXM: value->be32 = ofputil_port_to_ofp11(u16_to_ofp(ntohs(value->be16))); break; diff --git a/lib/meta-flow.h b/lib/meta-flow.h index d3185e4e6..11502f0a8 100644 --- a/lib/meta-flow.h +++ b/lib/meta-flow.h @@ -118,6 +118,8 @@ enum mf_field_id { /* L4. */ MFF_TCP_SRC, /* be16 (used for IPv4 or IPv6) */ MFF_TCP_DST, /* be16 (used for IPv4 or IPv6) */ + MFF_TCP_FLAGS, /* be16, 12 bits (4 MSB zeroed, + * used for IPv4 or IPv6) */ MFF_UDP_SRC, /* be16 (used for IPv4 or IPv6) */ MFF_UDP_DST, /* be16 (used for IPv4 or IPv6) */ diff --git a/lib/nx-match.c b/lib/nx-match.c index 11cbff3d1..1a6fcaec0 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -530,6 +530,8 @@ nxm_put_ip(struct ofpbuf *b, const struct match *match, flow->tp_src, match->wc.masks.tp_src); nxm_put_16m(b, oxm ? OXM_OF_TCP_DST : NXM_OF_TCP_DST, flow->tp_dst, match->wc.masks.tp_dst); + nxm_put_16m(b, NXM_NX_TCP_FLAGS, + flow->tcp_flags, match->wc.masks.tcp_flags); } else if (flow->nw_proto == IPPROTO_UDP) { nxm_put_16m(b, oxm ? OXM_OF_UDP_SRC : NXM_OF_UDP_SRC, flow->tp_src, match->wc.masks.tp_src); @@ -570,7 +572,7 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match *match, int match_len; int i; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 21); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 22); /* Metadata. */ if (match->wc.masks.in_port.ofp_port) { diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 19fcc1c1a..af3370d88 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -131,6 +131,7 @@ odp_execute_set_action(struct ofpbuf *packet, const struct nlattr *a, case OVS_KEY_ATTR_ICMP: case OVS_KEY_ATTR_ICMPV6: case OVS_KEY_ATTR_ND: + case OVS_KEY_ATTR_TCP_FLAGS: case __OVS_KEY_ATTR_MAX: default: NOT_REACHED(); diff --git a/lib/odp-util.c b/lib/odp-util.c index 6875e013b..ce821c574 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -109,6 +109,7 @@ ovs_key_attr_to_string(enum ovs_key_attr attr, char *namebuf, size_t bufsize) case OVS_KEY_ATTR_IPV4: return "ipv4"; case OVS_KEY_ATTR_IPV6: return "ipv6"; case OVS_KEY_ATTR_TCP: return "tcp"; + case OVS_KEY_ATTR_TCP_FLAGS: return "tcp_flags"; case OVS_KEY_ATTR_UDP: return "udp"; case OVS_KEY_ATTR_SCTP: return "sctp"; case OVS_KEY_ATTR_ICMP: return "icmp"; @@ -735,6 +736,7 @@ odp_flow_key_attr_len(uint16_t type) case OVS_KEY_ATTR_IPV4: return sizeof(struct ovs_key_ipv4); case OVS_KEY_ATTR_IPV6: return sizeof(struct ovs_key_ipv6); case OVS_KEY_ATTR_TCP: return sizeof(struct ovs_key_tcp); + case OVS_KEY_ATTR_TCP_FLAGS: return 2; case OVS_KEY_ATTR_UDP: return sizeof(struct ovs_key_udp); case OVS_KEY_ATTR_SCTP: return sizeof(struct ovs_key_sctp); case OVS_KEY_ATTR_ICMP: return sizeof(struct ovs_key_icmp); @@ -1230,6 +1232,13 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma, } break; + case OVS_KEY_ATTR_TCP_FLAGS: + ds_put_format(ds, "0x%03"PRIx16, ntohs(nl_attr_get_be16(a))); + if (!is_exact) { + ds_put_format(ds, "/0x%03"PRIx16, ntohs(nl_attr_get_be16(ma))); + } + break; + case OVS_KEY_ATTR_UDP: if (!is_exact) { const struct ovs_key_udp *udp_mask = nl_attr_get(ma); @@ -2047,6 +2056,25 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names, } } + { + uint16_t tcp_flags, tcp_flags_mask; + int n = -1; + + if (mask && sscanf(s, "tcp_flags(%"SCNi16"/%"SCNi16")%n", + &tcp_flags, &tcp_flags_mask, &n) > 0 && n > 0) { + nl_msg_put_be16(key, OVS_KEY_ATTR_TCP_FLAGS, htons(tcp_flags)); + nl_msg_put_be16(mask, OVS_KEY_ATTR_TCP_FLAGS, htons(tcp_flags_mask)); + return n; + } else if (sscanf(s, "tcp_flags(%"SCNi16")%n", &tcp_flags, &n) > 0 && n > 0) { + nl_msg_put_be16(key, OVS_KEY_ATTR_TCP_FLAGS, htons(tcp_flags)); + if (mask) { + nl_msg_put_be16(mask, OVS_KEY_ATTR_TCP_FLAGS, + htons(UINT16_MAX)); + } + return n; + } + } + { int udp_src; int udp_dst; @@ -2559,6 +2587,10 @@ odp_flow_key_from_flow__(struct ofpbuf *buf, const struct flow *data, sizeof *tcp_key); tcp_key->tcp_src = data->tp_src; tcp_key->tcp_dst = data->tp_dst; + + if (data->tcp_flags) { + nl_msg_put_be16(buf, OVS_KEY_ATTR_TCP_FLAGS, data->tcp_flags); + } } else if (flow->nw_proto == IPPROTO_UDP) { struct ovs_key_udp *udp_key; @@ -2944,6 +2976,10 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], flow->tp_dst = tcp_key->tcp_dst; expected_bit = OVS_KEY_ATTR_TCP; } + if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TCP_FLAGS)) { + expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TCP_FLAGS; + flow->tcp_flags = nl_attr_get_be16(attrs[OVS_KEY_ATTR_TCP_FLAGS]); + } } else if (src_flow->nw_proto == IPPROTO_UDP && (src_flow->dl_type == htons(ETH_TYPE_IP) || src_flow->dl_type == htons(ETH_TYPE_IPV6)) diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 8c200ce9f..a0b729315 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -84,7 +84,7 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask) void ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc) { - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 21); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 22); /* Initialize most of wc. */ flow_wildcards_init_catchall(wc); diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index f76500192..48d078d8f 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -1559,7 +1559,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, /* If 'struct flow' gets additional metadata, we'll need to zero it out * before traversing a patch port. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 21); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 22); if (!xport) { xlate_report(ctx, "Nonexistent output port"); diff --git a/tests/ofp-print.at b/tests/ofp-print.at index 87d5da8ea..d94e8d404 100644 --- a/tests/ofp-print.at +++ b/tests/ofp-print.at @@ -444,10 +444,10 @@ AT_CHECK([ovs-ofctl ofp-print "\ 00 00 50 54 00 00 00 06 50 54 00 00 00 05 08 00 \ 45 00 00 28 bd 12 00 00 40 06 3c 6a c0 a8 00 01 \ c0 a8 00 02 27 2f 00 00 78 50 cc 5b 57 af 42 1e \ -50 00 02 00 26 e8 00 00 00 00 00 00 00 00 \ +50 02 02 00 26 e8 00 00 00 00 00 00 00 00 \ "], [0], [dnl OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=3 (via no_match) data_len=60 buffer=0x00000111 -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:06,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=10031,tp_dst=0 tcp_csum:26e8 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:06,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=10031,tp_dst=0,tcp_flags=0x002 tcp_csum:26e8 ]) AT_CLEANUP @@ -458,13 +458,13 @@ AT_CHECK([ovs-ofctl ofp-print "\ 00 00 50 54 00 00 00 06 50 54 00 00 00 05 08 00 \ 45 00 00 28 bd 12 00 00 40 06 3c 6a c0 a8 00 01 \ c0 a8 00 02 27 2f 00 00 78 50 cc 5b 57 af 42 1e \ -50 00 02 00 26 e8 00 00 00 00 00 00 00 00 \ +50 10 02 00 26 e8 00 00 00 00 00 00 00 00 \ " 3], [0], [dnl OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=3 (via no_match) data_len=60 buffer=0x00000111 -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:06,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=10031,tp_dst=0 tcp_csum:26e8 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:06,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=10031,tp_dst=0,tcp_flags=0x010 tcp_csum:26e8 00000000 50 54 00 00 00 06 50 54-00 00 00 05 08 00 45 00 00000010 00 28 bd 12 00 00 40 06-3c 6a c0 a8 00 01 c0 a8 -00000020 00 02 27 2f 00 00 78 50-cc 5b 57 af 42 1e 50 00 +00000020 00 02 27 2f 00 00 78 50-cc 5b 57 af 42 1e 50 10 00000030 02 00 26 e8 00 00 00 00-00 00 00 00 ]) AT_CLEANUP @@ -631,7 +631,7 @@ b9 7c c0 a8 00 02 c0 a8 00 01 00 00 2b 60 00 00 \ 00 00 00 00 \ "], [0], [dnl OFPT_PACKET_OUT (xid=0x0): in_port=1 actions=output:3 data_len=60 -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=11104 tcp_csum:6d75 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=11104,tcp_flags=0x014 tcp_csum:6d75 ]) AT_CLEANUP @@ -646,7 +646,7 @@ b9 7c c0 a8 00 02 c0 a8 00 01 00 00 2b 60 00 00 \ 00 00 00 00 \ " 3], [0], [dnl OFPT_PACKET_OUT (xid=0x0): in_port=1 actions=output:3 data_len=60 -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=11104 tcp_csum:6d75 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=11104,tcp_flags=0x014 tcp_csum:6d75 00000000 50 54 00 00 00 05 50 54-00 00 00 06 08 00 45 00 00000010 00 28 00 00 40 00 40 06-b9 7c c0 a8 00 02 c0 a8 00000020 00 01 00 00 2b 60 00 00-00 00 6a 4f 2b 58 50 14 @@ -677,7 +677,7 @@ b9 7c c0 a8 00 02 c0 a8 00 01 00 00 2b 60 00 00 \ 00 00 00 00 \ "], [0], [dnl OFPT_PACKET_OUT (OF1.2) (xid=0x8858dfc5): in_port=LOCAL actions=FLOOD data_len=60 -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=11104 tcp_csum:6d75 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=11104,tcp_flags=0x014 tcp_csum:6d75 ]) AT_CLEANUP @@ -2071,11 +2071,11 @@ ff ff ff ff 00 40 01 07 00 00 00 00 00 00 00 09 \ ff ff ff ff ff ff 00 00 00 00 82 82 82 82 82 82 \ 80 81 81 81 81 81 81 00 00 50 08 00 45 00 00 28 \ 00 00 00 00 00 06 32 05 53 53 53 53 54 54 54 54 \ -00 55 00 56 00 00 00 00 00 00 00 00 50 00 00 00 \ +00 55 00 56 00 00 00 00 00 00 00 00 50 02 00 00 \ 31 6d 00 00 00 00 00 00 00 00 \ "], [0], [dnl NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 tun_id=0x6 metadata=0x5a5a5a5a5a5a5a5a reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=86 tcp_csum:316d +tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=86,tcp_flags=0x002 tcp_csum:316d ]) AT_CLEANUP @@ -2092,15 +2092,15 @@ ff ff ff ff 00 40 01 07 00 00 00 00 00 00 00 09 \ ff ff ff ff ff ff 00 00 00 00 82 82 82 82 82 82 \ 80 81 81 81 81 81 81 00 00 50 08 00 45 00 00 28 \ 00 00 00 00 00 06 32 05 53 53 53 53 54 54 54 54 \ -00 55 00 56 00 00 00 00 00 00 00 00 50 00 00 00 \ +00 55 00 56 00 00 00 00 00 00 00 00 50 01 00 00 \ 31 6d 00 00 00 00 00 00 00 00 \ " 3], [0], [dnl NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 tun_id=0x6 metadata=0x5a5a5a5a5a5a5a5a reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=86 tcp_csum:316d +tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=86,tcp_flags=0x001 tcp_csum:316d 00000000 82 82 82 82 82 82 80 81-81 81 81 81 81 00 00 50 00000010 08 00 45 00 00 28 00 00-00 00 00 06 32 05 53 53 00000020 53 53 54 54 54 54 00 55-00 56 00 00 00 00 00 00 -00000030 00 00 50 00 00 00 31 6d-00 00 00 00 00 00 00 00 +00000030 00 00 50 01 00 00 31 6d-00 00 00 00 00 00 00 00 ]) AT_CLEANUP diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index c569463d1..9e0ea4ba2 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -317,60 +317,60 @@ dnl Flow miss. AT_CHECK([ovs-ofctl monitor -P openflow10 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log]) for i in 1 2 3 ; do - ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)' + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9),tcp_flags(0x010)' done OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) ovs-appctl -t ovs-ofctl exit AT_CHECK([cat ofctl_monitor.log], [0], [dnl OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9 tcp_csum:0 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=0x010 tcp_csum:0 dnl OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9 tcp_csum:0 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=0x010 tcp_csum:0 dnl OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9 tcp_csum:0 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=9,tcp_flags=0x010 tcp_csum:0 ]) dnl Singleton controller action. AT_CHECK([ovs-ofctl monitor -P openflow10 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log]) for i in 1 2 3 ; do - ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=10)' + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=10:11:11:11:11:11,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=10),tcp_flags(0x002)' done OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) ovs-appctl -t ovs-ofctl exit AT_CHECK([cat ofctl_monitor.log], [0], [dnl OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via action) data_len=60 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10 tcp_csum:0 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=0x002 tcp_csum:0 dnl OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via action) data_len=60 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10 tcp_csum:0 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=0x002 tcp_csum:0 dnl OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via action) data_len=60 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10 tcp_csum:0 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=10:11:11:11:11:11,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=0x002 tcp_csum:0 ]) dnl Modified controller action. AT_CHECK([ovs-ofctl monitor -P openflow10 br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log]) for i in 1 2 3 ; do - ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=30:33:33:33:33:33,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=10)' + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=30:33:33:33:33:33,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=10),tcp_flags(0x001)' done OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6]) ovs-appctl -t ovs-ofctl exit AT_CHECK([cat ofctl_monitor.log], [0], [dnl OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=15,dl_vlan_pcp=0,dl_src=30:33:33:33:33:33,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10 tcp_csum:0 +tcp,metadata=0,in_port=0,dl_vlan=15,dl_vlan_pcp=0,dl_src=30:33:33:33:33:33,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=0x001 tcp_csum:0 dnl OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=15,dl_vlan_pcp=0,dl_src=30:33:33:33:33:33,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10 tcp_csum:0 +tcp,metadata=0,in_port=0,dl_vlan=15,dl_vlan_pcp=0,dl_src=30:33:33:33:33:33,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=0x001 tcp_csum:0 dnl OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=15,dl_vlan_pcp=0,dl_src=30:33:33:33:33:33,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10 tcp_csum:0 +tcp,metadata=0,in_port=0,dl_vlan=15,dl_vlan_pcp=0,dl_src=30:33:33:33:33:33,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=10,tcp_flags=0x001 tcp_csum:0 ]) dnl Modified VLAN controller action. @@ -384,13 +384,13 @@ ovs-appctl -t ovs-ofctl exit AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:44:41,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64 tcp_csum:0 +tcp,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:44:41,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tcp_flags=0x000 tcp_csum:0 dnl NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:44:41,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64 tcp_csum:0 +tcp,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:44:41,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tcp_flags=0x000 tcp_csum:0 dnl NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=64 in_port=1 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:44:41,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64 tcp_csum:0 +tcp,metadata=0,in_port=0,dl_vlan=99,dl_vlan_pcp=1,dl_src=40:44:44:44:44:41,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tcp_flags=0x000 tcp_csum:0 ]) dnl Modified MPLS controller action. @@ -424,13 +424,13 @@ ovs-appctl -t ovs-ofctl exit AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=60 in_port=1 (via action) data_len=60 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=41:44:44:44:44:42,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64 tcp_csum:0 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=41:44:44:44:44:42,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tcp_flags=0x000 tcp_csum:0 dnl NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=60 in_port=1 (via action) data_len=60 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=41:44:44:44:44:42,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64 tcp_csum:0 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=41:44:44:44:44:42,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tcp_flags=0x000 tcp_csum:0 dnl NXT_PACKET_IN (xid=0x0): cookie=0xa total_len=60 in_port=1 (via action) data_len=60 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=41:44:44:44:44:42,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64 tcp_csum:0 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=41:44:44:44:44:42,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tcp_flags=0x000 tcp_csum:0 ]) dnl Modified MPLS controller action. @@ -613,51 +613,51 @@ ovs-appctl -t ovs-ofctl exit AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=60:66:66:66:66:66,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=80,tp_dst=0 tcp_csum:7744 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=60:66:66:66:66:66,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=80,tp_dst=0,tcp_flags=0x000 tcp_csum:7744 dnl NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=60:66:66:66:66:66,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=80,tp_dst=0 tcp_csum:7744 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=60:66:66:66:66:66,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=80,tp_dst=0,tcp_flags=0x000 tcp_csum:7744 dnl NXT_PACKET_IN (xid=0x0): cookie=0xd total_len=58 in_port=1 (via action) data_len=58 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=60:66:66:66:66:66,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=80,tp_dst=0 tcp_csum:7744 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=60:66:66:66:66:66,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=80,tp_dst=0,tcp_flags=0x000 tcp_csum:7744 ]) dnl Checksum TCP. AT_CHECK([ovs-ofctl monitor br0 65534 -P nxm --detach --no-chdir --pidfile 2> ofctl_monitor.log]) for i in 1 ; do - ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=20:22:22:22:22:22,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=11)' + ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=20:22:22:22:22:22,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=11),tcp_flags(0x001)' done OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 18]) ovs-appctl -t ovs-ofctl exit AT_CHECK([cat ofctl_monitor.log], [0], [dnl NXT_PACKET_IN (xid=0x0): cookie=0x1 total_len=60 in_port=1 (via action) data_len=60 (unbuffered) -tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11 tcp_csum:0 +tcp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=0x001 tcp_csum:0 dnl NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x3 total_len=64 in_port=1 reg0=0x1 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11 tcp_csum:0 +tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=0x001 tcp_csum:0 dnl NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x4 total_len=64 in_port=1 reg0=0x1 reg1=0x2 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11 tcp_csum:0 +tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=0x001 tcp_csum:0 dnl NXT_PACKET_IN (xid=0x0): table_id=3 cookie=0x5 total_len=64 in_port=1 reg0=0x1 reg1=0x2 reg2=0x3 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11 tcp_csum:0 +tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=0x001 tcp_csum:0 dnl NXT_PACKET_IN (xid=0x0): table_id=4 cookie=0x6 total_len=64 in_port=1 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11 tcp_csum:1a03 +tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=0x001 tcp_csum:1a03 dnl NXT_PACKET_IN (xid=0x0): table_id=5 cookie=0x7 total_len=64 in_port=1 tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11 tcp_csum:3205 +tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=8,tp_dst=11,tcp_flags=0x001 tcp_csum:3205 dnl NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x8 total_len=64 in_port=1 tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=85,tp_dst=11 tcp_csum:31b8 +tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=85,tp_dst=11,tcp_flags=0x001 tcp_csum:31b8 dnl NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=85,tp_dst=86 tcp_csum:316d +tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=85,tp_dst=86,tcp_flags=0x001 tcp_csum:316d dnl NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 (unbuffered) -tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=85,tp_dst=86 tcp_csum:316d +tcp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=85,tp_dst=86,tcp_flags=0x001 tcp_csum:316d ]) dnl Checksum UDP. diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index 131beaf85..7bb5b6ec3 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -539,6 +539,13 @@ NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(06) NXM_OF_TCP_DST_W(FDE0/ffff) NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(06) NXM_OF_TCP_DST_W(FDE0/0000) NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(07) NXM_OF_TCP_DST(4231) +# TCP flags +NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(06) NXM_NX_TCP_FLAGS(0131) +NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(06) NXM_NX_TCP_FLAGS_W(00F0/0FF0) +NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(06) NXM_NX_TCP_FLAGS_W(01E2/ffff) +NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(06) NXM_NX_TCP_FLAGS_W(00E1/0000) +NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(07) NXM_NX_TCP_FLAGS(4321) + # UDP source port NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(11) NXM_OF_UDP_SRC(8732) NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(11) NXM_OF_UDP_SRC_W(0132/01FF) @@ -826,6 +833,13 @@ NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_DST(fde0) NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06) nx_pull_match() returned error OFPBMC_BAD_PREREQ +# TCP flags +NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_NX_TCP_FLAGS(0131) +NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_NX_TCP_FLAGS_W(00f0/0ff0) +NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_NX_TCP_FLAGS(01e2) +NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06) +nx_pull_match() returned error OFPBMC_BAD_PREREQ + # UDP source port NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_SRC(8732) NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(11), NXM_OF_UDP_SRC_W(0132/01ff) @@ -2380,3 +2394,62 @@ OFPT_HELLO (xid=0x1): 00000000 01 00 00 0b 00 00 00 01-41 42 43 |........ABC | ]) AT_CLEANUP + +AT_SETUP([tcp flags - filtering]) +OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \ + -- add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2]) +AT_DATA([flows.txt], [dnl + in_port=1,tcp,tp_dst=80,tcp_flags=0x02/0x17,action=2 # Allow outbound web traffic bare-SYN + in_port=1,tcp,tp_dst=80,tcp_flags=0x10/0x10,action=2 # Allow outbound web traffic with ACK bit + in_port=1,tcp,tp_dst=80,tcp_flags=0x04/0x04,action=2 # Allow outbound web traffic with RST bit + in_port=2,tcp,tp_src=80,tcp_flags=0x10/0x10,action=1 # Allow inbound web traffic with ACK bit + in_port=2,tcp,tp_src=80,tcp_flags=0x04/0x04,action=1 # Allow inbound web traffic with RST bit + priority=0,in_port=1,action=drop # Default drop outbound + priority=0,in_port=2,action=drop # Default drop inbound +]) + +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) + +AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl + p1 1/1: (dummy) + p2 2/2: (dummy) +]) + +dnl Outbound web traffic with base-SYN +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=80),tcp_flags(0x002)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: 2 +]) + +dnl Outbopund web traffic with ACK bit +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=80),tcp_flags(0x110)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: 2 +]) + +dnl Outbound web traffic with RST bit +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=80),tcp_flags(0x104)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: 2 +]) + +dnl Inbound web traffic with ACK bit +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=6,tos=0,ttl=64,frag=no),tcp(src=80,dst=8),tcp_flags(0x010)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: 1 +]) + +dnl Inbound web traffic with RST bit +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=6,tos=0,ttl=64,frag=no),tcp(src=80,dst=8),tcp_flags(0x014)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: 1 +]) + +dnl Inbound web traffic with SYN bit without ACK or RST bits +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=6,tos=0,ttl=64,frag=no),tcp(src=80,dst=8),tcp_flags(0xfeb)'], [0], [stdout]) +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: drop +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 75ea43b2c..81c90bdd5 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -716,6 +716,40 @@ Like the exact-match forms of \fBtp_src\fR and \fBtp_dst\fR described above, the bitwise match forms apply only when \fBdl_type\fR and \fBnw_proto\fR specify TCP or UDP or SCTP. . +.IP \fBtcp_flags=\fIflags\fB/\fImask\fR +Bitwise match on TCP flags. The \fIflags\fR and \fImask\fR are 16-bit +numbers written in decimal or in hexadecimal prefixed by \fB0x\fR. +Each 1-bit in \fImask\fR requires that the corresponding bit in +\fIflags\fR must match. Each 0-bit in \fImask\fR causes the corresponding +bit to be ignored. +.IP +TCP protocol currently defines 9 flag bits, and additional 3 bits are +reserved (must be transmitted as zero), see RFCs 793, 3168, and 3540. +The flag bits are, numbering from the least significant bit: +.RS +.IP "\fB0: FIN\fR" +No more data from sender. +.IP "\fB1: SYN\fR" +Synchronize sequence numbers. +.IP "\fB2: RST\fR" +Reset the connection. +.IP "\fB3: PSH\fR" +Push function. +.IP "\fB4: ACK\fR" +Acknowledgement field significant. +.IP "\fB5: URG\fR" +Urgent pointer field significant. +.IP "\fB6: ECE\fR" +ECN Echo. +.IP "\fB7: CWR\fR" +Congestion Windows Reduced. +.IP "\fB8: NS\fR" +Nonce Sum. +.IP "\fB9-11:\fR" +Reserved. +.IP "\fB12-15:\fR" +Not matchable, must be zero. +.RE .IP \fBicmp_type=\fItype\fR .IQ \fBicmp_code=\fIcode\fR When \fBdl_type\fR and \fBnw_proto\fR specify ICMP or ICMPv6, \fItype\fR -- 2.43.0