From: Jesse Gross Date: Wed, 8 Jul 2015 23:02:30 +0000 (-0700) Subject: tunneling: Allow matching and setting tunnel 'OAM' flag. X-Git-Tag: v2.5.0~922 X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Fovs.git;a=commitdiff_plain;h=b666962be3b2772bec76c2df0c1aec90ce373b36 tunneling: Allow matching and setting tunnel 'OAM' flag. Several encapsulation formats have the concept of an 'OAM' bit which typically is used with networking tracing tools to distinguish test packets from real traffic. OVS already internally has support for this, however, it doesn't do anything with it and it also isn't exposed for controllers to use. This enables support through OpenFlow. There are several other tunnel flags which are consumed internally by OVS. It's not clear that it makes sense to use them externally so this does not expose those flags - although it should be easy to do so if necessary in the future. Signed-off-by: Jesse Gross Acked-by: Ben Pfaff --- diff --git a/NEWS b/NEWS index b08919b5b..f118c97e3 100644 --- a/NEWS +++ b/NEWS @@ -9,7 +9,8 @@ Post-v2.4.0 * OpenFlow 1.4+ "importance" is now considered for flow eviction. * OpenFlow 1.4+ OFPTC_EVICTION is now implemented. * OpenFlow 1.4+ OFPMP_TABLE_DESC is now implemented. - - Support for matching and generating options with Geneve tunnels. + - Support for matching/generating options as well as the OAM bit with + Geneve tunnels. - Support Multicast Listener Discovery (MLDv1 and MLDv2). - Add 'symmetric_l3l4' and 'symmetric_l3l4+udp' hash functions. diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h index 16a4a7a34..465b19de6 100644 --- a/include/openflow/nicira-ext.h +++ b/include/openflow/nicira-ext.h @@ -500,6 +500,9 @@ OFP_ASSERT(sizeof(struct nx_async_config) == 24); #define NX_IP_FRAG_ANY (1 << 0) /* Is this a fragment? */ #define NX_IP_FRAG_LATER (1 << 1) /* Is this a fragment with nonzero offset? */ +/* Bits in the value of NXM_NX_TUN_FLAGS. */ +#define NX_TUN_FLAG_OAM (1 << 0) /* Is this an OAM packet? */ + /* ## --------------------- ## */ /* ## Requests and replies. ## */ /* ## --------------------- ## */ diff --git a/lib/flow.c b/lib/flow.c index e47347b2f..e9ae81328 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -123,7 +123,7 @@ struct mf_ctx { * away. Some GCC versions gave warnings on ALWAYS_INLINE, so these are * defined as macros. */ -#if (FLOW_WC_SEQ != 32) +#if (FLOW_WC_SEQ != 33) #define MINIFLOW_ASSERT(X) ovs_assert(X) BUILD_MESSAGE("FLOW_WC_SEQ changed: miniflow_extract() will have runtime " "assertions enabled. Consider updating FLOW_WC_SEQ after " @@ -770,12 +770,16 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata) { int i; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 32); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); match_init_catchall(flow_metadata); if (flow->tunnel.tun_id != htonll(0)) { match_set_tun_id(flow_metadata, flow->tunnel.tun_id); } + if (flow->tunnel.flags & FLOW_TNL_PUB_F_MASK) { + match_set_tun_flags(flow_metadata, + flow->tunnel.flags & FLOW_TNL_PUB_F_MASK); + } if (flow->tunnel.ip_src != htonl(0)) { match_set_tun_src(flow_metadata, flow->tunnel.ip_src); } @@ -1118,7 +1122,7 @@ void flow_wildcards_init_for_packet(struct flow_wildcards *wc, memset(&wc->masks, 0x0, sizeof wc->masks); /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 32); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); if (flow->tunnel.ip_dst) { if (flow->tunnel.flags & FLOW_TNL_F_KEY) { @@ -1222,7 +1226,7 @@ uint64_t flow_wc_map(const struct flow *flow) { /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 32); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); uint64_t map = (flow->tunnel.ip_dst) ? MINIFLOW_MAP(tunnel) : 0; @@ -1274,7 +1278,7 @@ void flow_wildcards_clear_non_packet_fields(struct flow_wildcards *wc) { /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 32); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); memset(&wc->masks.metadata, 0, sizeof wc->masks.metadata); memset(&wc->masks.regs, 0, sizeof wc->masks.regs); @@ -1898,7 +1902,7 @@ flow_push_mpls(struct flow *flow, int n, ovs_be16 mpls_eth_type, flow->mpls_lse[0] = set_mpls_lse_values(ttl, tc, 1, htonl(label)); /* Clear all L3 and L4 fields and dp_hash. */ - BUILD_ASSERT(FLOW_WC_SEQ == 32); + BUILD_ASSERT(FLOW_WC_SEQ == 33); memset((char *) flow + FLOW_SEGMENT_2_ENDS_AT, 0, sizeof(struct flow) - FLOW_SEGMENT_2_ENDS_AT); flow->dp_hash = 0; diff --git a/lib/flow.h b/lib/flow.h index 5a7399c41..392cb59c7 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -39,7 +39,7 @@ struct match; /* 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 32 +#define FLOW_WC_SEQ 33 /* Number of Open vSwitch extension 32-bit registers. */ #define FLOW_N_REGS 8 @@ -64,10 +64,19 @@ BUILD_ASSERT_DECL(FLOW_N_REGS % 2 == 0); /* Even. */ BUILD_ASSERT_DECL(FLOW_NW_FRAG_ANY == NX_IP_FRAG_ANY); BUILD_ASSERT_DECL(FLOW_NW_FRAG_LATER == NX_IP_FRAG_LATER); -#define FLOW_TNL_F_DONT_FRAGMENT (1 << 0) -#define FLOW_TNL_F_CSUM (1 << 1) -#define FLOW_TNL_F_KEY (1 << 2) -#define FLOW_TNL_F_OAM (1 << 3) +/* Some flags are exposed through OpenFlow while others are used only + * internally. */ + +/* Public flags */ +#define FLOW_TNL_F_OAM (1 << 0) + +#define FLOW_TNL_PUB_F_MASK ((1 << 1) - 1) +BUILD_ASSERT_DECL(FLOW_TNL_F_OAM == NX_TUN_FLAG_OAM); + +/* Private flags */ +#define FLOW_TNL_F_DONT_FRAGMENT (1 << 1) +#define FLOW_TNL_F_CSUM (1 << 2) +#define FLOW_TNL_F_KEY (1 << 3) #define FLOW_TNL_F_MASK ((1 << 4) - 1) @@ -157,7 +166,7 @@ BUILD_ASSERT_DECL(sizeof(struct flow) % sizeof(uint64_t) == 0); /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */ BUILD_ASSERT_DECL(offsetof(struct flow, igmp_group_ip4) + sizeof(uint32_t) == sizeof(struct flow_tnl) + 192 - && FLOW_WC_SEQ == 32); + && FLOW_WC_SEQ == 33); /* Incremental points at which flow classification may be performed in * segments. diff --git a/lib/match.c b/lib/match.c index ce431de69..a638dfd96 100644 --- a/lib/match.c +++ b/lib/match.c @@ -225,6 +225,8 @@ match_set_tun_flags(struct match *match, uint16_t flags) void match_set_tun_flags_masked(struct match *match, uint16_t flags, uint16_t mask) { + mask &= FLOW_TNL_PUB_F_MASK; + match->wc.masks.tunnel.flags = mask; match->flow.tunnel.flags = flags & mask; } @@ -899,7 +901,10 @@ format_flow_tunnel(struct ds *s, const struct match *match) ds_put_format(s, "tun_ttl=%"PRIu8",", tnl->ip_ttl); } if (wc->masks.tunnel.flags) { - format_flags(s, flow_tun_flag_to_string, tnl->flags, '|'); + format_flags_masked(s, "tun_flags", flow_tun_flag_to_string, + tnl->flags, + wc->masks.tunnel.flags & FLOW_TNL_F_MASK, + FLOW_TNL_F_MASK); ds_put_char(s, ','); } tun_metadata_match_format(s, match); @@ -918,7 +923,7 @@ match_format(const struct match *match, struct ds *s, int priority) int i; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 32); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); if (priority != OFP_DEFAULT_PRIORITY) { ds_put_format(s, "priority=%d,", priority); diff --git a/lib/meta-flow.c b/lib/meta-flow.c index a2abc4dbc..0c01414c9 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -182,10 +182,13 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc) case MFF_TUN_DST: return !wc->masks.tunnel.ip_dst; case MFF_TUN_ID: + return !wc->masks.tunnel.tun_id; case MFF_TUN_TOS: + return !wc->masks.tunnel.ip_tos; case MFF_TUN_TTL: + return !wc->masks.tunnel.ip_ttl; case MFF_TUN_FLAGS: - return !wc->masks.tunnel.tun_id; + return !(wc->masks.tunnel.flags & FLOW_TNL_PUB_F_MASK); case MFF_TUN_GBP_ID: return !wc->masks.tunnel.gbp_id; case MFF_TUN_GBP_FLAGS: @@ -484,7 +487,6 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value) case MFF_TUN_DST: case MFF_TUN_TOS: case MFF_TUN_TTL: - case MFF_TUN_FLAGS: case MFF_TUN_GBP_ID: case MFF_TUN_GBP_FLAGS: CASE_MFF_TUN_METADATA: @@ -564,6 +566,9 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value) case MFF_MPLS_BOS: return !(value->u8 & ~(MPLS_BOS_MASK >> MPLS_BOS_SHIFT)); + case MFF_TUN_FLAGS: + return !(value->be16 & ~htons(FLOW_TNL_PUB_F_MASK)); + case MFF_N_IDS: default: OVS_NOT_REACHED(); @@ -596,7 +601,7 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow, value->be32 = flow->tunnel.ip_dst; break; case MFF_TUN_FLAGS: - value->be16 = htons(flow->tunnel.flags); + value->be16 = htons(flow->tunnel.flags & FLOW_TNL_PUB_F_MASK); break; case MFF_TUN_GBP_ID: value->be16 = flow->tunnel.gbp_id; @@ -1098,7 +1103,8 @@ mf_set_flow_value(const struct mf_field *mf, flow->tunnel.ip_dst = value->be32; break; case MFF_TUN_FLAGS: - flow->tunnel.flags = ntohs(value->be16); + flow->tunnel.flags = (flow->tunnel.flags & ~FLOW_TNL_PUB_F_MASK) | + ntohs(value->be16); break; case MFF_TUN_GBP_ID: flow->tunnel.gbp_id = value->be16; @@ -2047,9 +2053,8 @@ mf_from_tcp_flags_string(const char *s, ovs_be16 *flagsp, ovs_be16 *maskp) static char * mf_from_tun_flags_string(const char *s, ovs_be16 *flagsp, ovs_be16 *maskp) { - *maskp = OVS_BE16_MAX; return parse_mf_flags(s, flow_tun_flag_to_string, "tunnel", flagsp, - htons(FLOW_TNL_F_MASK), NULL); + htons(FLOW_TNL_PUB_F_MASK), maskp); } /* Parses 's', a string value for field 'mf', into 'value' and 'mask'. Returns @@ -2180,9 +2185,10 @@ mf_format_frag_string(uint8_t value, uint8_t mask, struct ds *s) } static void -mf_format_tnl_flags_string(ovs_be16 value, struct ds *s) +mf_format_tnl_flags_string(ovs_be16 value, ovs_be16 mask, struct ds *s) { - format_flags(s, flow_tun_flag_to_string, ntohs(value), '|'); + format_flags_masked(s, NULL, flow_tun_flag_to_string, ntohs(value), + ntohs(mask) & FLOW_TNL_PUB_F_MASK, FLOW_TNL_PUB_F_MASK); } static void @@ -2245,7 +2251,8 @@ mf_format(const struct mf_field *mf, break; case MFS_TNL_FLAGS: - mf_format_tnl_flags_string(value->be16, s); + mf_format_tnl_flags_string(value->be16, + mask ? mask->be16 : OVS_BE16_MAX, s); break; case MFS_TCP_FLAGS: diff --git a/lib/meta-flow.h b/lib/meta-flow.h index f622d0b0a..8feefcc40 100644 --- a/lib/meta-flow.h +++ b/lib/meta-flow.h @@ -370,17 +370,28 @@ enum OVS_PACKED_ENUM mf_field_id { /* "tun_flags". * - * Combination of FLOW_TNL_F_* bitmapped flags that indicate properties of - * a tunneled packet. Internal use only, not programmable from controller. + * Flags representing aspects of tunnel behavior. + * + * This field currently only has a single flag defined: + * + * - NX_TUN_FLAG_OAM: The tunnel protocol indicated that this is an + * OAM control packet. + * + * The switch may reject matches against values that it is not aware of. + * + * Note that it is possible for newer version of Open vSwitch to + * introduce additional flags with varying meaning. It is therefore not + * recommended to use an exact match on this field since the behavior of + * these new flags is unknown and should be ignored. * * For non-tunneled packets, the value is 0. * - * Type: be16. - * Maskable: no. + * Type: be16 (low 1 bits). + * Maskable: bitwise. * Formatting: tunnel flags. * Prerequisites: none. - * Access: read-only. - * NXM: none. + * Access: read/write. + * NXM: NXM_NX_TUN_FLAGS(104) since v2.5. * OXM: none. */ MFF_TUN_FLAGS, diff --git a/lib/nx-match.c b/lib/nx-match.c index 2cc990cba..a8b11830d 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -895,7 +895,7 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match, int match_len; int i; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 32); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); /* Metadata. */ if (match->wc.masks.dp_hash) { @@ -1000,6 +1000,8 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match, flow->tunnel.tun_id, match->wc.masks.tunnel.tun_id); /* Other tunnel metadata. */ + nxm_put_16m(b, MFF_TUN_FLAGS, oxm, + htons(flow->tunnel.flags), htons(match->wc.masks.tunnel.flags)); nxm_put_32m(b, MFF_TUN_SRC, oxm, flow->tunnel.ip_src, match->wc.masks.tunnel.ip_src); nxm_put_32m(b, MFF_TUN_DST, oxm, diff --git a/lib/odp-util.h b/lib/odp-util.h index f65b00666..989bb81d3 100644 --- a/lib/odp-util.h +++ b/lib/odp-util.h @@ -135,7 +135,7 @@ void odp_portno_names_destroy(struct hmap *portno_names); * add another field and forget to adjust this value. */ #define ODPUTIL_FLOW_KEY_BYTES 512 -BUILD_ASSERT_DECL(FLOW_WC_SEQ == 32); +BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); /* A buffer with sufficient size and alignment to hold an nlattr-formatted flow * key. An array of "struct nlattr" might not, in theory, be sufficiently diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 646bae7f5..7e2ee4baa 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -199,7 +199,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 == 32); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); /* Initialize most of wc. */ flow_wildcards_init_catchall(wc); diff --git a/ofproto/ofproto-dpif-rid.h b/ofproto/ofproto-dpif-rid.h index dc533ce4a..a614a4d46 100644 --- a/ofproto/ofproto-dpif-rid.h +++ b/ofproto/ofproto-dpif-rid.h @@ -91,7 +91,7 @@ struct rule; /* Metadata for restoring pipeline context after recirculation. Helpers * are inlined below to keep them together with the definition for easier * updates. */ -BUILD_ASSERT_DECL(FLOW_WC_SEQ == 32); +BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); struct recirc_metadata { /* Metadata in struct flow. */ diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 731dd7894..803c268f2 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -2829,7 +2829,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 == 32); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33); memset(&flow_tnl, 0, sizeof flow_tnl); if (!xport) { diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index 42f760e19..91c13ab75 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -459,7 +459,7 @@ tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow, } } - flow->tunnel.flags = (cfg->dont_fragment ? FLOW_TNL_F_DONT_FRAGMENT : 0) + flow->tunnel.flags |= (cfg->dont_fragment ? FLOW_TNL_F_DONT_FRAGMENT : 0) | (cfg->csum ? FLOW_TNL_F_CSUM : 0) | (cfg->out_key_present ? FLOW_TNL_F_KEY : 0); diff --git a/tests/odp.at b/tests/odp.at index 63bbe69fd..a50a9cd07 100644 --- a/tests/odp.at +++ b/tests/odp.at @@ -117,7 +117,7 @@ skb_mark(0x1234/0xfff0),in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14: echo echo '# Valid forms with tunnel header.' - sed 's/^/tunnel(tun_id=0x7f10354\/0xff,src=10.10.10.10\/255.255.255.0,dst=20.20.20.20\/255.255.255.0,ttl=64,vxlan(gbp(id=10\/0xff,flags=0xb)),flags(csum|key)),/' odp-base.txt + sed 's/^/tunnel(tun_id=0x7f10354\/0xff,src=10.10.10.10\/255.255.255.0,dst=20.20.20.20\/255.255.255.0,ttl=64,vxlan(gbp(id=10\/0xff,flags=0xb)),flags(oam|csum|key)),/' odp-base.txt echo echo '# Valid forms with tunnel header (wildcard flag).' diff --git a/tests/ofproto.at b/tests/ofproto.at index 232dd2fe9..7d78b5770 100644 --- a/tests/ofproto.at +++ b/tests/ofproto.at @@ -1510,7 +1510,7 @@ OVS_VSWITCHD_START instructions: meter,apply_actions,clear_actions,write_actions,write_metadata$goto Write-Actions and Apply-Actions features: actions: output group set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue - supported on Set-Field: tun_id tun_src tun_dst tun_gbp_id tun_gbp_flags tun_metadata0 tun_metadata1 tun_metadata2 tun_metadata3 tun_metadata4 tun_metadata5 tun_metadata6 tun_metadata7 tun_metadata8 tun_metadata9 tun_metadata10 tun_metadata11 tun_metadata12 tun_metadata13 tun_metadata14 tun_metadata15 tun_metadata16 tun_metadata17 tun_metadata18 tun_metadata19 tun_metadata20 tun_metadata21 tun_metadata22 tun_metadata23 tun_metadata24 tun_metadata25 tun_metadata26 tun_metadata27 tun_metadata28 tun_metadata29 tun_metadata30 tun_metadata31 tun_metadata32 tun_metadata33 tun_metadata34 tun_metadata35 tun_metadata36 tun_metadata37 tun_metadata38 tun_metadata39 tun_metadata40 tun_metadata41 tun_metadata42 tun_metadata43 tun_metadata44 tun_metadata45 tun_metadata46 tun_metadata47 tun_metadata48 tun_metadata49 tun_metadata50 tun_metadata51 tun_metadata52 tun_metadata53 tun_metadata54 tun_metadata55 tun_metadata56 tun_metadata57 tun_metadata58 tun_metadata59 tun_metadata60 tun_metadata61 tun_metadata62 tun_metadata63 metadata in_port in_port_oxm pkt_mark reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 xreg0 xreg1 xreg2 xreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst nd_target nd_sll nd_tll + supported on Set-Field: tun_id tun_src tun_dst tun_flags tun_gbp_id tun_gbp_flags tun_metadata0 tun_metadata1 tun_metadata2 tun_metadata3 tun_metadata4 tun_metadata5 tun_metadata6 tun_metadata7 tun_metadata8 tun_metadata9 tun_metadata10 tun_metadata11 tun_metadata12 tun_metadata13 tun_metadata14 tun_metadata15 tun_metadata16 tun_metadata17 tun_metadata18 tun_metadata19 tun_metadata20 tun_metadata21 tun_metadata22 tun_metadata23 tun_metadata24 tun_metadata25 tun_metadata26 tun_metadata27 tun_metadata28 tun_metadata29 tun_metadata30 tun_metadata31 tun_metadata32 tun_metadata33 tun_metadata34 tun_metadata35 tun_metadata36 tun_metadata37 tun_metadata38 tun_metadata39 tun_metadata40 tun_metadata41 tun_metadata42 tun_metadata43 tun_metadata44 tun_metadata45 tun_metadata46 tun_metadata47 tun_metadata48 tun_metadata49 tun_metadata50 tun_metadata51 tun_metadata52 tun_metadata53 tun_metadata54 tun_metadata55 tun_metadata56 tun_metadata57 tun_metadata58 tun_metadata59 tun_metadata60 tun_metadata61 tun_metadata62 tun_metadata63 metadata in_port in_port_oxm pkt_mark reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 xreg0 xreg1 xreg2 xreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst nd_target nd_sll nd_tll matching: dp_hash: arbitrary mask recirc_id: exact match or wildcard @@ -1518,6 +1518,7 @@ OVS_VSWITCHD_START tun_id: arbitrary mask tun_src: arbitrary mask tun_dst: arbitrary mask + tun_flags: arbitrary mask tun_gbp_id: arbitrary mask tun_gbp_flags: arbitrary mask tun_metadata0: arbitrary mask @@ -1658,7 +1659,7 @@ AT_CHECK( # Check that the configuration was updated. mv expout orig-expout sed 's/classifier/main/ -141s/1000000/1024/' < orig-expout > expout +142s/1000000/1024/' < orig-expout > expout AT_CHECK([ovs-ofctl -O OpenFlow13 dump-table-features br0 | sed '/^$/d /^OFPST_TABLE_FEATURES/d'], [0], [expout]) OVS_VSWITCHD_STOP diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index 38d5b355c..2383aebfb 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -9,7 +9,8 @@ for test_case in \ 'tun_src=1.2.3.4/0.0.0.1 NXM,OXM' \ 'tun_dst=1.2.3.4 NXM,OXM' \ 'tun_dst=1.2.3.4/0.0.0.1 NXM,OXM' \ - 'tun_flags=0 none' \ + 'tun_flags=1 NXM,OXM' \ + 'tun_flags=+oam NXM,OXM' \ 'tun_tos=0 none' \ 'tun_ttl=0 none' \ 'tun_gbp_id=0 NXM,OXM' \ @@ -302,18 +303,6 @@ AT_CHECK([ovs-ofctl --protocols OpenFlow11 add-flow br0 'ip actions=mod_tp_dst:1 ]) AT_CLEANUP -AT_SETUP([ovs-ofctl parse-flows (With Tunnel-Parameters)]) -AT_DATA([flows.txt], [[ -tun_id=0x1234000056780000/0xffff0000ffff0000,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=0x3,tun_ttl=20,tun_flags=key|csum actions=drop -]]) - -AT_CHECK([ovs-ofctl parse-flows flows.txt -], [1], [usable protocols: none -], [stderr]) - -AT_CLEANUP - - AT_SETUP([ovs-ofctl parse-flows (skb_priority)]) AT_DATA([flows.txt], [[ skb_priority=0x12341234,tcp,tp_src=123,actions=flood diff --git a/tests/tunnel.at b/tests/tunnel.at index 24cbdf2de..00e577c58 100644 --- a/tests/tunnel.at +++ b/tests/tunnel.at @@ -82,28 +82,28 @@ AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl dnl Tunnel CE and encapsulated packet CE AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),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=3,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=3,tun_ttl=64,0,in_port=1,nw_ecn=3,nw_frag=no + [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=3,tun_ttl=64,tun_flags=-df-csum-key,in_port=1,nw_ecn=3,nw_frag=no Datapath actions: 2 ]) dnl Tunnel CE and encapsulated packet ECT(1) AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),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=1,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=3,tun_ttl=64,0,in_port=1,nw_ecn=1,nw_frag=no + [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=3,tun_ttl=64,tun_flags=-df-csum-key,in_port=1,nw_ecn=1,nw_frag=no Datapath actions: set(ipv4(tos=0x3/0x3)),2 ]) dnl Tunnel CE and encapsulated packet ECT(2) AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),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=2,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=3,tun_ttl=64,0,in_port=1,nw_ecn=2,nw_frag=no + [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=3,tun_ttl=64,tun_flags=-df-csum-key,in_port=1,nw_ecn=2,nw_frag=no Datapath actions: set(ipv4(tos=0x3/0x3)),2 ]) dnl Tunnel CE and encapsulated packet Non-ECT AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(src=1.1.1.1,dst=2.2.2.2,tos=0x3,ttl=64,flags()),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)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=3,tun_ttl=64,0,in_port=1,nw_ecn=0,nw_frag=no + [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=2.2.2.2,tun_tos=3,tun_ttl=64,tun_flags=-df-csum-key,in_port=1,nw_ecn=0,nw_frag=no Datapath actions: drop ]) OVS_VSWITCHD_STOP(["/dropping tunnel packet marked ECN CE but is not ECN capable/d"]) @@ -436,14 +436,14 @@ AT_CHECK([tail -1 stdout], [0], dnl Option match AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x0,src=1.1.1.1,dst=1.1.1.2,ttl=64,geneve({class=0xffff,type=0,len=4,0xb}),flags(df|key)),in_port(6081),skb_mark(0),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=1.1.1.2,tun_tos=0,tun_ttl=64,df|key,tun_metadata0=0xb/0xf,in_port=1,nw_frag=no + [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=1.1.1.2,tun_tos=0,tun_ttl=64,tun_flags=+df-csum+key,tun_metadata0=0xb/0xf,in_port=1,nw_frag=no Datapath actions: 2 ]) dnl Skip unknown option AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x0,src=1.1.1.1,dst=1.1.1.2,ttl=64,geneve({class=0xffff,type=0,len=4,0xb}{class=0xffff,type=2,len=4,0xc}),flags(df|key)),in_port(6081),skb_mark(0),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=1.1.1.2,tun_tos=0,tun_ttl=64,df|key,tun_metadata0=0xb/0xf,in_port=1,nw_frag=no + [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=1.1.1.2,tun_tos=0,tun_ttl=64,tun_flags=+df-csum+key,tun_metadata0=0xb/0xf,in_port=1,nw_frag=no Datapath actions: 2 ]) @@ -468,7 +468,7 @@ AT_CHECK([ovs-ofctl add-geneve-map br0 "{class=0xffff,type=3,len=8}->tun_metadat AT_CHECK([ovs-ofctl add-flow br0 tun_metadata3=0x1234567890abcdef,actions=2]) AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(0),tunnel(tun_id=0x0,src=1.1.1.1,dst=1.1.1.2,ttl=64,geneve({class=0xffff,type=3,len=8,0x1234567890abcdef}),flags(df|key)),in_port(6081),skb_mark(0),eth_type(0x0800),ipv4(frag=no)'], [0], [stdout]) AT_CHECK([tail -2 stdout], [0], - [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=1.1.1.2,tun_tos=0,tun_ttl=64,df|key,tun_metadata0=0/0xf,tun_metadata3=0x1234567890abcdef,in_port=1,nw_frag=no + [Megaflow: pkt_mark=0,recirc_id=0,ip,tun_id=0,tun_src=1.1.1.1,tun_dst=1.1.1.2,tun_tos=0,tun_ttl=64,tun_flags=+df-csum+key,tun_metadata0=0/0xf,tun_metadata3=0x1234567890abcdef,in_port=1,nw_frag=no Datapath actions: 2 ]) diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 512945900..92a29f395 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -1149,6 +1149,26 @@ if \fImask\fR is specified, then a 1-bit in \fImask\fR indicates that the corresponding bit in \fItunnel-id\fR must match exactly, and a 0-bit wildcards that bit. . +.IP \fBtun_flags=\fIflags\fR +Matches flags indicating various aspects of the tunnel encapsulation. Currently, +there is only one flag defined: +.IP +\fBoam\fR: The tunnel protocol indicated that this is an OAM control packet. +.IP +Flags can be prefixed by \fB+\fR or \fB-\fR to indicate that the flag should +be matched as either present or not present, respectively. In addition, flags +can be specified without a prefix and separated by \fB|\fR to indicate an exact +match. +.IP +Note that it is possible for newer version of Open vSwitch to introduce +additional flags with varying meaning. It is therefore not recommended to use +an exact match on this field since the behavior of these new flags is unknown +and should be ignored. +.IP +For non-tunneled packets, the value is 0. +.IP +This field was introduced in Open vSwitch 2.5. +. .IP \fBtun_src=\fIip\fR[\fB/\fInetmask\fR] .IQ \fBtun_dst=\fIip\fR[\fB/\fInetmask\fR] Matches tunnel IPv4 source (or destination) address \fIip\fR. Only packets