From 8368c090cab8b604818cc3db321f1ed8531f27a4 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 20 Jan 2011 15:29:00 -0800 Subject: [PATCH] Implement arbitrary bitwise masks for tun_id field. This was documented to work, but not implemented. Requested-by: Pankaj Thakkar --- lib/classifier.c | 31 +++++++++++++++------- lib/classifier.h | 4 ++- lib/flow.c | 10 +++++-- lib/flow.h | 9 +++---- lib/nx-match.c | 48 +++++++++++++++++++++++++++++---- lib/nx-match.def | 2 +- lib/ofp-parse.c | 37 +++++++++++++++++++++++--- lib/ofp-util.c | 57 +++++++++++++++++++++++++++++++--------- tests/ovs-ofctl.at | 7 +++++ tests/test-classifier.c | 8 ++++-- utilities/ovs-ofctl.8.in | 19 +++++++++----- 11 files changed, 184 insertions(+), 48 deletions(-) diff --git a/lib/classifier.c b/lib/classifier.c index ba10272f7..b05b491e8 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010 Nicira Networks. + * Copyright (c) 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -130,8 +130,15 @@ cls_rule_set_reg_masked(struct cls_rule *rule, unsigned int reg_idx, void cls_rule_set_tun_id(struct cls_rule *rule, ovs_be64 tun_id) { - rule->wc.wildcards &= ~FWW_TUN_ID; - rule->flow.tun_id = tun_id; + cls_rule_set_tun_id_masked(rule, tun_id, htonll(UINT64_MAX)); +} + +void +cls_rule_set_tun_id_masked(struct cls_rule *rule, + ovs_be64 tun_id, ovs_be64 mask) +{ + rule->wc.tun_id_mask = mask; + rule->flow.tun_id = tun_id & mask; } void @@ -393,8 +400,16 @@ cls_rule_format(const struct cls_rule *rule, struct ds *s) break; } } - if (!(w & FWW_TUN_ID)) { - ds_put_format(s, "tun_id=0x%"PRIx64",", ntohll(f->tun_id)); + switch (wc->tun_id_mask) { + case 0: + break; + case CONSTANT_HTONLL(UINT64_MAX): + ds_put_format(s, "tun_id=%#"PRIx64",", ntohll(f->tun_id)); + break; + default: + ds_put_format(s, "tun_id=%#"PRIx64"/%#"PRIx64",", + ntohll(f->tun_id), ntohll(wc->tun_id_mask)); + break; } if (!(w & FWW_IN_PORT)) { ds_put_format(s, "in_port=%"PRIu16",", @@ -940,7 +955,7 @@ flow_equal_except(const struct flow *a, const struct flow *b, } } - return ((wc & FWW_TUN_ID || a->tun_id == b->tun_id) + return (!((a->tun_id ^ b->tun_id) & wildcards->tun_id_mask) && !((a->nw_src ^ b->nw_src) & wildcards->nw_src_mask) && !((a->nw_dst ^ b->nw_dst) & wildcards->nw_dst_mask) && (wc & FWW_IN_PORT || a->in_port == b->in_port) @@ -973,9 +988,7 @@ zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards) for (i = 0; i < FLOW_N_REGS; i++) { flow->regs[i] &= wildcards->reg_masks[i]; } - if (wc & FWW_TUN_ID) { - flow->tun_id = 0; - } + flow->tun_id &= wildcards->tun_id_mask; flow->nw_src &= wildcards->nw_src_mask; flow->nw_dst &= wildcards->nw_dst_mask; if (wc & FWW_IN_PORT) { diff --git a/lib/classifier.h b/lib/classifier.h index 453417da6..7b347e7b9 100644 --- a/lib/classifier.h +++ b/lib/classifier.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010 Nicira Networks. + * Copyright (c) 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -78,6 +78,8 @@ void cls_rule_set_reg(struct cls_rule *, unsigned int reg_idx, uint32_t value); void cls_rule_set_reg_masked(struct cls_rule *, unsigned int reg_idx, uint32_t value, uint32_t mask); void cls_rule_set_tun_id(struct cls_rule *, ovs_be64 tun_id); +void cls_rule_set_tun_id_masked(struct cls_rule *, + ovs_be64 tun_id, ovs_be64 mask); void cls_rule_set_in_port(struct cls_rule *, uint16_t odp_port); void cls_rule_set_dl_type(struct cls_rule *, ovs_be16); void cls_rule_set_dl_src(struct cls_rule *, const uint8_t[6]); diff --git a/lib/flow.c b/lib/flow.c index e7ed2a97e..42f850fbd 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -302,6 +302,7 @@ void flow_wildcards_init_catchall(struct flow_wildcards *wc) { wc->wildcards = FWW_ALL; + wc->tun_id_mask = htonll(0); wc->nw_src_mask = htonl(0); wc->nw_dst_mask = htonl(0); memset(wc->reg_masks, 0, sizeof wc->reg_masks); @@ -315,6 +316,7 @@ void flow_wildcards_init_exact(struct flow_wildcards *wc) { wc->wildcards = 0; + wc->tun_id_mask = htonll(UINT64_MAX); wc->nw_src_mask = htonl(UINT32_MAX); wc->nw_dst_mask = htonl(UINT32_MAX); memset(wc->reg_masks, 0xff, sizeof wc->reg_masks); @@ -330,6 +332,7 @@ flow_wildcards_is_exact(const struct flow_wildcards *wc) int i; if (wc->wildcards + || wc->tun_id_mask != htonll(UINT64_MAX) || wc->nw_src_mask != htonl(UINT32_MAX) || wc->nw_dst_mask != htonl(UINT32_MAX) || wc->vlan_tci_mask != htons(UINT16_MAX)) { @@ -356,6 +359,7 @@ flow_wildcards_combine(struct flow_wildcards *dst, int i; dst->wildcards = src1->wildcards | src2->wildcards; + dst->tun_id_mask = src1->tun_id_mask & src2->tun_id_mask; dst->nw_src_mask = src1->nw_src_mask & src2->nw_src_mask; dst->nw_dst_mask = src1->nw_dst_mask & src2->nw_dst_mask; for (i = 0; i < FLOW_N_REGS; i++) { @@ -371,7 +375,7 @@ flow_wildcards_hash(const struct flow_wildcards *wc) /* If you change struct flow_wildcards and thereby trigger this * assertion, please check that the new struct flow_wildcards has no holes * in it before you update the assertion. */ - BUILD_ASSERT_DECL(sizeof *wc == 16 + FLOW_N_REGS * 4); + BUILD_ASSERT_DECL(sizeof *wc == 24 + FLOW_N_REGS * 4); return hash_bytes(wc, sizeof *wc, 0); } @@ -384,6 +388,7 @@ flow_wildcards_equal(const struct flow_wildcards *a, int i; if (a->wildcards != b->wildcards + || a->tun_id_mask != b->tun_id_mask || a->nw_src_mask != b->nw_src_mask || a->nw_dst_mask != b->nw_dst_mask || a->vlan_tci_mask != b->vlan_tci_mask) { @@ -414,6 +419,7 @@ flow_wildcards_has_extra(const struct flow_wildcards *a, } return (a->wildcards & ~b->wildcards + || (a->tun_id_mask & b->tun_id_mask) != b->tun_id_mask || (a->nw_src_mask & b->nw_src_mask) != b->nw_src_mask || (a->nw_dst_mask & b->nw_dst_mask) != b->nw_dst_mask || (a->vlan_tci_mask & b->vlan_tci_mask) != b->vlan_tci_mask); diff --git a/lib/flow.h b/lib/flow.h index ee460e386..966f1d684 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -107,18 +107,17 @@ typedef unsigned int OVS_BITWISE flow_wildcards_t; #define FWW_TP_DST ((OVS_FORCE flow_wildcards_t) (1 << 7)) /* Same meanings as corresponding OFPFW_* bits, but differ in value. */ #define FWW_NW_TOS ((OVS_FORCE flow_wildcards_t) (1 << 1)) -/* No OFPFW_* bits, but they do have corresponding OVSFW_* bits. */ -#define FWW_TUN_ID ((OVS_FORCE flow_wildcards_t) (1 << 8)) /* No corresponding OFPFW_* or OVSFW_* bits. */ -#define FWW_ETH_MCAST ((OVS_FORCE flow_wildcards_t) (1 << 9)) +#define FWW_ETH_MCAST ((OVS_FORCE flow_wildcards_t) (1 << 8)) /* multicast bit only */ -#define FWW_ALL ((OVS_FORCE flow_wildcards_t) (((1 << 10)) - 1)) +#define FWW_ALL ((OVS_FORCE flow_wildcards_t) (((1 << 9)) - 1)) /* Information on wildcards for a flow, as a supplement to "struct flow". * * Note that the meaning of 1-bits in 'wildcards' is opposite that of 1-bits in * the rest of the members. */ struct flow_wildcards { + ovs_be64 tun_id_mask; /* 1-bit in each significant tun_id bit. */ flow_wildcards_t wildcards; /* 1-bit in each FWW_* wildcarded field. */ uint32_t reg_masks[FLOW_N_REGS]; /* 1-bit in each significant regs bit. */ ovs_be32 nw_src_mask; /* 1-bit in each significant nw_src bit. */ diff --git a/lib/nx-match.c b/lib/nx-match.c index fc3af68df..392ea869f 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -320,8 +320,21 @@ parse_nxm_entry(struct cls_rule *rule, const struct nxm_field *f, /* Tunnel ID. */ case NFI_NXM_NX_TUN_ID: - flow->tun_id = get_unaligned_be64(value); - return 0; + if (wc->tun_id_mask) { + return NXM_DUP_TYPE; + } else { + cls_rule_set_tun_id(rule, get_unaligned_be64(value)); + return 0; + } + case NFI_NXM_NX_TUN_ID_W: + if (wc->tun_id_mask) { + return NXM_DUP_TYPE; + } else { + ovs_be64 tun_id = get_unaligned_be64(value); + ovs_be64 tun_mask = get_unaligned_be64(mask); + cls_rule_set_tun_id_masked(rule, tun_id, tun_mask); + return 0; + } /* Registers. */ case NFI_NXM_NX_REG0: @@ -533,6 +546,31 @@ nxm_put_64(struct ofpbuf *b, uint32_t header, ovs_be64 value) ofpbuf_put(b, &value, sizeof value); } +static void +nxm_put_64w(struct ofpbuf *b, uint32_t header, ovs_be64 value, ovs_be64 mask) +{ + nxm_put_header(b, header); + ofpbuf_put(b, &value, sizeof value); + ofpbuf_put(b, &mask, sizeof mask); +} + +static void +nxm_put_64m(struct ofpbuf *b, uint32_t header, ovs_be64 value, ovs_be64 mask) +{ + switch (mask) { + case 0: + break; + + case CONSTANT_HTONLL(UINT64_MAX): + nxm_put_64(b, header, value); + break; + + default: + nxm_put_64w(b, NXM_MAKE_WILD_HEADER(header), value, mask); + break; + } +} + static void nxm_put_eth(struct ofpbuf *b, uint32_t header, const uint8_t value[ETH_ADDR_LEN]) @@ -657,9 +695,7 @@ nx_put_match(struct ofpbuf *b, const struct cls_rule *cr) } /* Tunnel ID. */ - if (!(wc & FWW_TUN_ID)) { - nxm_put_64(b, NXM_NX_TUN_ID, flow->tun_id); - } + nxm_put_64m(b, NXM_NX_TUN_ID, flow->tun_id, cr->wc.tun_id_mask); /* Registers. */ for (i = 0; i < FLOW_N_REGS; i++) { @@ -1125,6 +1161,7 @@ nxm_read_field(const struct nxm_field *src, const struct flow *flow) #error #endif + case NFI_NXM_NX_TUN_ID_W: case NFI_NXM_OF_ETH_DST_W: case NFI_NXM_OF_VLAN_TCI_W: case NFI_NXM_OF_IP_SRC_W: @@ -1189,6 +1226,7 @@ nxm_write_field(const struct nxm_field *dst, struct flow *flow, case NFI_NXM_OF_UDP_DST: case NFI_NXM_OF_ICMP_TYPE: case NFI_NXM_OF_ICMP_CODE: + case NFI_NXM_NX_TUN_ID_W: case NFI_NXM_OF_ETH_DST_W: case NFI_NXM_OF_VLAN_TCI_W: case NFI_NXM_OF_IP_SRC_W: diff --git a/lib/nx-match.def b/lib/nx-match.def index 9c113eb28..09f375bdf 100644 --- a/lib/nx-match.def +++ b/lib/nx-match.def @@ -38,7 +38,7 @@ DEFINE_FIELD (OF_ICMP_CODE, FWW_TP_DST, ETH_TYPE_IP, IP_TYPE_ICMP, false) DEFINE_FIELD (OF_ARP_OP, FWW_NW_PROTO, ETH_TYPE_ARP, 0, false) DEFINE_FIELD_M(OF_ARP_SPA, 0, ETH_TYPE_ARP, 0, false) DEFINE_FIELD_M(OF_ARP_TPA, 0, ETH_TYPE_ARP, 0, false) -DEFINE_FIELD (NX_TUN_ID, FWW_TUN_ID, 0, 0, true) +DEFINE_FIELD_M(NX_TUN_ID, 0, 0, 0, true) DEFINE_FIELD_M(NX_REG0, 0, 0, 0, true) #if FLOW_N_REGS >= 2 diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index f8464b99d..7fed553ea 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Nicira Networks. + * Copyright (c) 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -128,6 +128,35 @@ str_to_ip(const char *str_, ovs_be32 *ip, ovs_be32 *maskp) free(str); } +static void +str_to_tun_id(const char *str, ovs_be64 *tun_idp, ovs_be64 *maskp) +{ + uint64_t tun_id, mask; + char *tail; + + errno = 0; + tun_id = strtoull(str, &tail, 0); + if (errno || (*tail != '\0' && *tail != '/')) { + goto error; + } + + if (*tail == '/') { + mask = strtoull(tail + 1, &tail, 0); + if (errno || *tail != '\0') { + goto error; + } + } else { + mask = UINT64_MAX; + } + + *tun_idp = htonll(tun_id); + *maskp = htonll(mask); + return; + +error: + ovs_fatal(0, "%s: bad syntax for tunnel id", str); +} + static void * put_action(struct ofpbuf *b, size_t size, uint16_t type) { @@ -448,7 +477,7 @@ parse_protocol(const char *name, const struct protocol **p_out) } #define FIELDS \ - FIELD(F_TUN_ID, "tun_id", FWW_TUN_ID) \ + FIELD(F_TUN_ID, "tun_id", 0) \ FIELD(F_IN_PORT, "in_port", FWW_IN_PORT) \ FIELD(F_DL_VLAN, "dl_vlan", 0) \ FIELD(F_DL_VLAN_PCP, "dl_vlan_pcp", 0) \ @@ -502,12 +531,14 @@ parse_field_value(struct cls_rule *rule, enum field_index index, const char *value) { uint8_t mac[ETH_ADDR_LEN]; + ovs_be64 tun_id, tun_mask; ovs_be32 ip, mask; uint16_t port_no; switch (index) { case F_TUN_ID: - cls_rule_set_tun_id(rule, htonll(str_to_u64(value))); + str_to_tun_id(value, &tun_id, &tun_mask); + cls_rule_set_tun_id_masked(rule, tun_id, tun_mask); break; case F_IN_PORT: diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 7aea3319e..ed2325c3c 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -132,9 +132,6 @@ ofputil_cls_rule_from_match(const struct ofp_match *match, if (flow_format == NXFF_TUN_ID_FROM_COOKIE && !(ofpfw & NXFW_TUN_ID)) { rule->flow.tun_id = htonll(ntohll(cookie) >> 32); - } else { - wc->wildcards |= FWW_TUN_ID; - rule->flow.tun_id = htonll(0); } if (ofpfw & OFPFW_DL_DST) { @@ -233,7 +230,7 @@ ofputil_cls_rule_to_match(const struct cls_rule *rule, /* Tunnel ID. */ if (flow_format == NXFF_TUN_ID_FROM_COOKIE) { - if (wc->wildcards & FWW_TUN_ID) { + if (wc->tun_id_mask == htonll(0)) { ofpfw |= NXFW_TUN_ID; } else { uint32_t cookie_lo = ntohll(cookie_in); @@ -829,6 +826,47 @@ regs_fully_wildcarded(const struct flow_wildcards *wc) return true; } +static inline bool +is_nxm_required(const struct cls_rule *rule, bool cookie_support, + ovs_be64 cookie) +{ + const struct flow_wildcards *wc = &rule->wc; + ovs_be32 cookie_hi; + + /* Only NXM supports separately wildcards the Ethernet multicast bit. */ + if (!(wc->wildcards & FWW_DL_DST) != !(wc->wildcards & FWW_ETH_MCAST)) { + return true; + } + + /* Only NXM supports matching registers. */ + if (!regs_fully_wildcarded(wc)) { + return true; + } + + switch (wc->tun_id_mask) { + case CONSTANT_HTONLL(0): + /* Other formats can fully wildcard tun_id. */ + break; + + case CONSTANT_HTONLL(UINT64_MAX): + /* Only NXM supports matching tunnel ID, unless there is a cookie and + * the top 32 bits of the cookie are the desired tunnel ID value. */ + cookie_hi = htonl(ntohll(cookie) >> 32); + if (!cookie_support + || (cookie_hi && cookie_hi != ntohll(rule->flow.tun_id))) { + return true; + } + break; + + default: + /* Only NXM supports partial matches on tunnel ID. */ + return true; + } + + /* Other formats can express this rule. */ + return false; +} + /* Returns the minimum nx_flow_format to use for sending 'rule' to a switch * (e.g. to add or remove a flow). 'cookie_support' should be true if the * command to be sent includes a flow cookie (as OFPT_FLOW_MOD does, for @@ -853,16 +891,9 @@ enum nx_flow_format ofputil_min_flow_format(const struct cls_rule *rule, bool cookie_support, ovs_be64 cookie) { - const struct flow_wildcards *wc = &rule->wc; - ovs_be32 cookie_hi = htonl(ntohll(cookie) >> 32); - - if (!(wc->wildcards & FWW_DL_DST) != !(wc->wildcards & FWW_ETH_MCAST) - || !regs_fully_wildcarded(wc) - || (!(wc->wildcards & FWW_TUN_ID) - && (!cookie_support - || (cookie_hi && cookie_hi != ntohll(rule->flow.tun_id))))) { + if (is_nxm_required(rule, cookie_support, cookie)) { return NXFF_NXM; - } else if (!(wc->wildcards & FWW_TUN_ID)) { + } else if (rule->wc.tun_id_mask != htonll(0)) { return NXFF_TUN_ID_FROM_COOKIE; } else { return NXFF_OPENFLOW10; diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index 143c59bd1..0648f067d 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -15,6 +15,7 @@ tun_id=0x1234,cookie=0x5678,actions=flood actions=set_tunnel:0x1234,set_tunnel64:0x9876,set_tunnel:0x123456789 actions=multipath(eth_src, 50, hrw, 12, 0, NXM_NX_REG0[0..3]),multipath(symmetric_l4, 1024, iter_hash, 5000, 5050, NXM_NX_REG0[0..12]) actions=drop +tun_id=0x1234000056780000/0xffff0000ffff0000,actions=drop ]]) AT_CHECK([ovs-ofctl parse-flows flows.txt ], [0], [stdout], [stderr]) @@ -32,6 +33,8 @@ OFPT_FLOW_MOD: ADD cookie:0x123400005678 actions=FLOOD OFPT_FLOW_MOD: ADD actions=set_tunnel:0x1234,set_tunnel64:0x9876,set_tunnel64:0x123456789 OFPT_FLOW_MOD: ADD actions=multipath(eth_src,50,hrw,12,0,NXM_NX_REG0[0..3]),multipath(symmetric_l4,1024,iter_hash,5000,5050,NXM_NX_REG0[0..12]) OFPT_FLOW_MOD: ADD actions=drop +NXT_SET_FLOW_FORMAT: format=nxm +NXT_FLOW_MOD: ADD tun_id=0x1234000056780000/0xffff0000ffff0000 actions=drop ]]) AT_CHECK([sed 's/.*|//' stderr], [0], [dnl normalization changed ofp_match, details: @@ -65,6 +68,7 @@ cookie=0x123456789abcdef hard_timeout=10 priority=60000 actions=controller actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note tun_id=0x1234,cookie=0x5678,actions=flood actions=drop +tun_id=0x1234000056780000/0xffff0000ffff0000,actions=drop ]) AT_CHECK([ovs-ofctl -F nxm parse-flows flows.txt], [0], [stdout]) AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0], [dnl @@ -78,6 +82,7 @@ NXT_FLOW_MOD: ADD priority=60000 cookie:0x123456789abcdef hard:10 actions=CONTRO NXT_FLOW_MOD: ADD actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00 NXT_FLOW_MOD: ADD tun_id=0x1234 cookie:0x5678 actions=FLOOD NXT_FLOW_MOD: ADD actions=drop +NXT_FLOW_MOD: ADD tun_id=0x1234000056780000/0xffff0000ffff0000 actions=drop ]) AT_CLEANUP @@ -214,6 +219,7 @@ NXM_OF_ARP_TPA_W(C0D80000/FFFF0000) # Tunnel ID. NXM_NX_TUN_ID(00000000abcdef01) +NXM_NX_TUN_ID_W(84200000abcdef01/84200000FFFFFFFF) # Register 0. NXM_NX_REG0(acebdf56) @@ -331,6 +337,7 @@ nx_pull_match() returned error 44010104 # Tunnel ID. NXM_NX_TUN_ID(00000000abcdef01) +NXM_NX_TUN_ID_W(84200000abcdef01/84200000ffffffff) # Register 0. NXM_NX_REG0(acebdf56) diff --git a/tests/test-classifier.c b/tests/test-classifier.c index 63a7adacc..e1f93a09d 100644 --- a/tests/test-classifier.c +++ b/tests/test-classifier.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010 Nicira Networks. + * Copyright (c) 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,7 +44,7 @@ /* struct flow all-caps */ \ /* FWW_* bit(s) member name name */ \ /* -------------------------- ----------- -------- */ \ - CLS_FIELD(FWW_TUN_ID, tun_id, TUN_ID) \ + CLS_FIELD(0, tun_id, TUN_ID) \ CLS_FIELD(0, nw_src, NW_SRC) \ CLS_FIELD(0, nw_dst, NW_DST) \ CLS_FIELD(FWW_IN_PORT, in_port, IN_PORT) \ @@ -201,6 +201,8 @@ match(const struct cls_rule *wild, const struct flow *fixed) } else if (f_idx == CLS_F_IDX_VLAN_TCI) { eq = !((fixed->vlan_tci ^ wild->flow.vlan_tci) & wild->wc.vlan_tci_mask); + } else if (f_idx == CLS_F_IDX_TUN_ID) { + eq = !((fixed->tun_id ^ wild->flow.tun_id) & wild->wc.tun_id_mask); } else { NOT_REACHED(); } @@ -463,6 +465,8 @@ make_rule(int wc_fields, unsigned int priority, int value_pat) rule->cls_rule.wc.nw_dst_mask = htonl(UINT32_MAX); } else if (f_idx == CLS_F_IDX_VLAN_TCI) { rule->cls_rule.wc.vlan_tci_mask = htons(UINT16_MAX); + } else if (f_idx == CLS_F_IDX_TUN_ID) { + rule->cls_rule.wc.tun_id_mask = htonll(UINT64_MAX); } else { NOT_REACHED(); } diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 0a2a5e988..750477483 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -337,20 +337,25 @@ as a decimal number between 0 and 255, inclusive. .IP When \fBdl_type\fR and \fBnw_proto\fR take other values, the values of these settings are ignored (see \fBFlow Syntax\fR above). -.IP \fBtun_id=\fItunnel\-id\fR -Matches tunnel identifier \fItunnel\-id\fR. Only packets that arrive +.IP \fBtun_id=\fItunnel-id\fR[\fB/\fImask\fR] +Matches tunnel identifier \fItunnel-id\fR. Only packets that arrive over a tunnel that carries a key (e.g. GRE with the RFC 2890 key -extension) will have a nonzero tunnel ID. +extension) will have a nonzero tunnel ID. If \fImask\fR is omitted, +\fItunnel-id\fR is the exact tunnel ID to match; \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_id\fR requires use of one of two Nicira extensions to OpenFlow: .RS .IP "NXM (Nicira Extended Match)" This extension fully supports \fBtun_id\fR. .IP "Tunnel ID from Cookie" -This extension supports \fBtun_id\fR with two caveats: the top 32 bits -of the \fBcookie\fR (see below) are used for \fItunnel\-id\fR and thus -unavailable for other use, and specifying \fBtun_id\fR on -\fBdump\-flows\fR or \fBdump\-aggregate\fR has no effect. +This extension supports \fBtun_id\fR with three caveats: the top 32 bits +of the \fBcookie\fR (see below) are used for \fItunnel-id\fR and thus +unavailable for other use, specifying \fBtun_id\fR on +\fBdump\-flows\fR or \fBdump\-aggregate\fR has no effect, and +\fImask\fR is not supported. .RE .IP When \fBtun_id\fR is specified, \fBovs\-ofctl\fR will automatically -- 2.43.0