summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorYi Yang <yi.y.yang@intel.com>2018-01-11 13:24:01 +0800
committerBen Pfaff <blp@ovn.org>2018-01-11 11:46:11 -0800
commit17553f27baa1d1883bed0d099f20e979cecd4a4c (patch)
treeaaf7b7135045ab177d672435ce01990175609560 /lib
parent74868f2c38f931cc355787152ebf9d9e9f1c8b37 (diff)
downloadopenvswitch-17553f27baa1d1883bed0d099f20e979cecd4a4c.tar.gz
nsh: add new flow key 'ttl'
IETF NSH draft added a new filed ttl in NSH header, this patch is to add new nsh key 'ttl' for it. Signed-off-by: Yi Yang <yi.y.yang@intel.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/flow.c23
-rw-r--r--lib/flow.h2
-rw-r--r--lib/match.c12
-rw-r--r--lib/meta-flow.c56
-rw-r--r--lib/meta-flow.xml139
-rw-r--r--lib/nx-match.c16
-rw-r--r--lib/odp-execute.c40
-rw-r--r--lib/odp-util.c130
-rw-r--r--lib/odp-util.h2
9 files changed, 273 insertions, 147 deletions
diff --git a/lib/flow.c b/lib/flow.c
index 964f7347f..f9d7c2a74 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -530,11 +530,10 @@ parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto,
}
bool
-parse_nsh(const void **datap, size_t *sizep, struct flow_nsh *key)
+parse_nsh(const void **datap, size_t *sizep, struct ovs_key_nsh *key)
{
const struct nsh_hdr *nsh = (const struct nsh_hdr *) *datap;
- uint8_t version, length, flags;
- uint32_t path_hdr;
+ uint8_t version, length, flags, ttl;
/* Check if it is long enough for NSH header, doesn't support
* MD type 2 yet
@@ -546,18 +545,17 @@ parse_nsh(const void **datap, size_t *sizep, struct flow_nsh *key)
version = nsh_get_ver(nsh);
flags = nsh_get_flags(nsh);
length = nsh_hdr_len(nsh);
+ ttl = nsh_get_ttl(nsh);
if (OVS_UNLIKELY(length > *sizep || version != 0)) {
return false;
}
key->flags = flags;
+ key->ttl = ttl;
key->mdtype = nsh->md_type;
key->np = nsh->next_proto;
-
- path_hdr = ntohl(get_16aligned_be32(&nsh->path_hdr));
- key->si = (path_hdr & NSH_SI_MASK) >> NSH_SI_SHIFT;
- key->spi = htonl((path_hdr & NSH_SPI_MASK) >> NSH_SPI_SHIFT);
+ key->path_hdr = nsh_get_path_hdr(nsh);
switch (key->mdtype) {
case NSH_M_TYPE1:
@@ -876,11 +874,11 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
miniflow_pad_to_64(mf, arp_tha);
}
} else if (dl_type == htons(ETH_TYPE_NSH)) {
- struct flow_nsh nsh;
+ struct ovs_key_nsh nsh;
if (OVS_LIKELY(parse_nsh(&data, &size, &nsh))) {
miniflow_push_words(mf, nsh, &nsh,
- sizeof(struct flow_nsh) /
+ sizeof(struct ovs_key_nsh) /
sizeof(uint64_t));
}
}
@@ -1684,10 +1682,10 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc,
return;
} else if (flow->dl_type == htons(ETH_TYPE_NSH)) {
WC_MASK_FIELD(wc, nsh.flags);
+ WC_MASK_FIELD(wc, nsh.ttl);
WC_MASK_FIELD(wc, nsh.mdtype);
WC_MASK_FIELD(wc, nsh.np);
- WC_MASK_FIELD(wc, nsh.spi);
- WC_MASK_FIELD(wc, nsh.si);
+ WC_MASK_FIELD(wc, nsh.path_hdr);
WC_MASK_FIELD(wc, nsh.context);
} else {
return; /* Unknown ethertype. */
@@ -1820,8 +1818,7 @@ flow_wc_map(const struct flow *flow, struct flowmap *map)
FLOWMAP_SET(map, nsh.flags);
FLOWMAP_SET(map, nsh.mdtype);
FLOWMAP_SET(map, nsh.np);
- FLOWMAP_SET(map, nsh.spi);
- FLOWMAP_SET(map, nsh.si);
+ FLOWMAP_SET(map, nsh.path_hdr);
FLOWMAP_SET(map, nsh.context);
}
}
diff --git a/lib/flow.h b/lib/flow.h
index b3128dab3..eb1e2bfc6 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -129,7 +129,7 @@ bool flow_compose(struct dp_packet *, const struct flow *, size_t);
bool parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto,
uint8_t *nw_frag);
ovs_be16 parse_dl_type(const struct eth_header *data_, size_t size);
-bool parse_nsh(const void **datap, size_t *sizep, struct flow_nsh *key);
+bool parse_nsh(const void **datap, size_t *sizep, struct ovs_key_nsh *key);
static inline uint64_t
flow_get_xreg(const struct flow *flow, int idx)
diff --git a/lib/match.c b/lib/match.c
index 8952c9934..b88049221 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -1260,11 +1260,19 @@ format_ct_label_masked(struct ds *s, const ovs_u128 *key, const ovs_u128 *mask)
static void
format_nsh_masked(struct ds *s, const struct flow *f, const struct flow *m)
{
+ ovs_be32 spi_mask = nsh_path_hdr_to_spi(m->nsh.path_hdr);
+ if (spi_mask == htonl(NSH_SPI_MASK >> NSH_SPI_SHIFT)) {
+ spi_mask = OVS_BE32_MAX;
+ }
format_uint8_masked(s, "nsh_flags", f->nsh.flags, m->nsh.flags);
+ format_uint8_masked(s, "nsh_ttl", f->nsh.ttl, m->nsh.ttl);
format_uint8_masked(s, "nsh_mdtype", f->nsh.mdtype, m->nsh.mdtype);
format_uint8_masked(s, "nsh_np", f->nsh.np, m->nsh.np);
- format_be32_masked_hex(s, "nsh_spi", f->nsh.spi, m->nsh.spi);
- format_uint8_masked(s, "nsh_si", f->nsh.si, m->nsh.si);
+
+ format_be32_masked_hex(s, "nsh_spi", nsh_path_hdr_to_spi(f->nsh.path_hdr),
+ spi_mask);
+ format_uint8_masked(s, "nsh_si", nsh_path_hdr_to_si(f->nsh.path_hdr),
+ nsh_path_hdr_to_si(m->nsh.path_hdr));
if (m->nsh.mdtype == UINT8_MAX && f->nsh.mdtype == NSH_M_TYPE1) {
format_be32_masked_hex(s, "nsh_c1", f->nsh.context[0],
m->nsh.context[0]);
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index beeddf1b6..ed41f5021 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -40,6 +40,7 @@
#include "openvswitch/ofp-errors.h"
#include "openvswitch/vlog.h"
#include "vl-mff-map.h"
+#include "openvswitch/nsh.h"
VLOG_DEFINE_THIS_MODULE(meta_flow);
@@ -361,14 +362,16 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
case MFF_NSH_FLAGS:
return !wc->masks.nsh.flags;
+ case MFF_NSH_TTL:
+ return !wc->masks.nsh.ttl;
case MFF_NSH_MDTYPE:
return !wc->masks.nsh.mdtype;
case MFF_NSH_NP:
return !wc->masks.nsh.np;
case MFF_NSH_SPI:
- return !wc->masks.nsh.spi;
+ return !(wc->masks.nsh.path_hdr & htonl(NSH_SPI_MASK));
case MFF_NSH_SI:
- return !wc->masks.nsh.si;
+ return !(wc->masks.nsh.path_hdr & htonl(NSH_SI_MASK));
case MFF_NSH_C1:
case MFF_NSH_C2:
case MFF_NSH_C3:
@@ -606,6 +609,8 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
case MFF_NSH_FLAGS:
return true;
+ case MFF_NSH_TTL:
+ return (value->u8 <= 63);
case MFF_NSH_MDTYPE:
return (value->u8 == 1 || value->u8 == 2);
case MFF_NSH_NP:
@@ -899,6 +904,9 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
case MFF_NSH_FLAGS:
value->u8 = flow->nsh.flags;
break;
+ case MFF_NSH_TTL:
+ value->u8 = flow->nsh.ttl;
+ break;
case MFF_NSH_MDTYPE:
value->u8 = flow->nsh.mdtype;
break;
@@ -906,10 +914,13 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
value->u8 = flow->nsh.np;
break;
case MFF_NSH_SPI:
- value->be32 = flow->nsh.spi;
+ value->be32 = nsh_path_hdr_to_spi(flow->nsh.path_hdr);
+ if (value->be32 == htonl(NSH_SPI_MASK >> NSH_SPI_SHIFT)) {
+ value->be32 = OVS_BE32_MAX;
+ }
break;
case MFF_NSH_SI:
- value->u8 = flow->nsh.si;
+ value->u8 = nsh_path_hdr_to_si(flow->nsh.path_hdr);
break;
case MFF_NSH_C1:
case MFF_NSH_C2:
@@ -1214,6 +1225,9 @@ mf_set_value(const struct mf_field *mf,
case MFF_NSH_FLAGS:
MATCH_SET_FIELD_UINT8(match, nsh.flags, value->u8);
break;
+ case MFF_NSH_TTL:
+ MATCH_SET_FIELD_UINT8(match, nsh.ttl, value->u8);
+ break;
case MFF_NSH_MDTYPE:
MATCH_SET_FIELD_UINT8(match, nsh.mdtype, value->u8);
break;
@@ -1221,10 +1235,12 @@ mf_set_value(const struct mf_field *mf,
MATCH_SET_FIELD_UINT8(match, nsh.np, value->u8);
break;
case MFF_NSH_SPI:
- MATCH_SET_FIELD_BE32(match, nsh.spi, value->be32);
+ match->wc.masks.nsh.path_hdr |= htonl(NSH_SPI_MASK);
+ nsh_path_hdr_set_spi(&match->flow.nsh.path_hdr, value->be32);
break;
case MFF_NSH_SI:
- MATCH_SET_FIELD_UINT8(match, nsh.si, value->u8);
+ match->wc.masks.nsh.path_hdr |= htonl(NSH_SI_MASK);
+ nsh_path_hdr_set_si(&match->flow.nsh.path_hdr, value->u8);
break;
case MFF_NSH_C1:
case MFF_NSH_C2:
@@ -1606,6 +1622,9 @@ mf_set_flow_value(const struct mf_field *mf,
case MFF_NSH_FLAGS:
flow->nsh.flags = value->u8;
break;
+ case MFF_NSH_TTL:
+ flow->nsh.ttl = value->u8;
+ break;
case MFF_NSH_MDTYPE:
flow->nsh.mdtype = value->u8;
break;
@@ -1613,10 +1632,10 @@ mf_set_flow_value(const struct mf_field *mf,
flow->nsh.np = value->u8;
break;
case MFF_NSH_SPI:
- flow->nsh.spi = value->be32;
+ nsh_path_hdr_set_spi(&flow->nsh.path_hdr, value->be32);
break;
case MFF_NSH_SI:
- flow->nsh.si = value->u8;
+ nsh_path_hdr_set_si(&flow->nsh.path_hdr, value->u8);
break;
case MFF_NSH_C1:
case MFF_NSH_C2:
@@ -1752,6 +1771,7 @@ mf_is_pipeline_field(const struct mf_field *mf)
case MFF_ND_SLL:
case MFF_ND_TLL:
case MFF_NSH_FLAGS:
+ case MFF_NSH_TTL:
case MFF_NSH_MDTYPE:
case MFF_NSH_NP:
case MFF_NSH_SPI:
@@ -2097,6 +2117,9 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str)
case MFF_NSH_FLAGS:
MATCH_SET_FIELD_MASKED(match, nsh.flags, 0, 0);
break;
+ case MFF_NSH_TTL:
+ MATCH_SET_FIELD_MASKED(match, nsh.ttl, 0, 0);
+ break;
case MFF_NSH_MDTYPE:
MATCH_SET_FIELD_MASKED(match, nsh.mdtype, 0, 0);
break;
@@ -2104,10 +2127,12 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str)
MATCH_SET_FIELD_MASKED(match, nsh.np, 0, 0);
break;
case MFF_NSH_SPI:
- MATCH_SET_FIELD_MASKED(match, nsh.spi, htonl(0), htonl(0));
+ match->wc.masks.nsh.path_hdr &= ~htonl(NSH_SPI_MASK);
+ nsh_path_hdr_set_spi(&match->flow.nsh.path_hdr, htonl(0));
break;
case MFF_NSH_SI:
- MATCH_SET_FIELD_MASKED(match, nsh.si, 0, 0);
+ match->wc.masks.nsh.path_hdr &= ~htonl(NSH_SI_MASK);
+ nsh_path_hdr_set_si(&match->flow.nsh.path_hdr, 0);
break;
case MFF_NSH_C1:
case MFF_NSH_C2:
@@ -2357,6 +2382,9 @@ mf_set(const struct mf_field *mf,
case MFF_NSH_FLAGS:
MATCH_SET_FIELD_MASKED(match, nsh.flags, value->u8, mask->u8);
break;
+ case MFF_NSH_TTL:
+ MATCH_SET_FIELD_MASKED(match, nsh.ttl, value->u8, mask->u8);
+ break;
case MFF_NSH_MDTYPE:
MATCH_SET_FIELD_MASKED(match, nsh.mdtype, value->u8, mask->u8);
break;
@@ -2364,10 +2392,14 @@ mf_set(const struct mf_field *mf,
MATCH_SET_FIELD_MASKED(match, nsh.np, value->u8, mask->u8);
break;
case MFF_NSH_SPI:
- MATCH_SET_FIELD_MASKED(match, nsh.spi, value->be32, mask->be32);
+ match->wc.masks.nsh.path_hdr |= mask->be32;
+ nsh_path_hdr_set_spi(&match->flow.nsh.path_hdr,
+ value->be32 & mask->be32);
break;
case MFF_NSH_SI:
- MATCH_SET_FIELD_MASKED(match, nsh.si, value->u8, mask->u8);
+ match->wc.masks.nsh.path_hdr |= htonl(mask->u8);
+ nsh_path_hdr_set_si(&match->flow.nsh.path_hdr,
+ value->u8 & mask->u8);
break;
case MFF_NSH_C1:
case MFF_NSH_C2:
diff --git a/lib/meta-flow.xml b/lib/meta-flow.xml
index 08ee0ece7..933d4b86b 100644
--- a/lib/meta-flow.xml
+++ b/lib/meta-flow.xml
@@ -1309,27 +1309,6 @@ tcp,tp_src=0x07c0/0xfff0
</field>
</group>
- <group title="Network Service Header">
- <field id="MFF_NSH_FLAGS"
- title="flags field (8 bits)"/>
- <field id="MFF_NSH_MDTYPE"
- title="mdtype field (8 bits)"/>
- <field id="MFF_NSH_NP"
- title="np (next protocol) field (8 bits)"/>
- <field id="MFF_NSH_SPI"
- title="spi (service path identifier) field (24 bits)"/>
- <field id="MFF_NSH_SI"
- title="si (service index) field (8 bits)"/>
- <field id="MFF_NSH_C1"
- title="c1 (Network Platform Context) field (32 bits)"/>
- <field id="MFF_NSH_C2"
- title="c2 (Network Shared Context) field (32 bits)"/>
- <field id="MFF_NSH_C3"
- title="c3 (Service Platform Context) field (32 bits)"/>
- <field id="MFF_NSH_C4"
- title="c4 (Service Shared Context) field (32 bits)"/>
- </group>
-
<group title="Tunnel">
<p>
The fields in this group relate to tunnels, which Open vSwitch
@@ -3964,7 +3943,7 @@ r r c c c.
listen for <code>OFPR_INVALID_TTL</code> ``packet-in'' messages via
OpenFlow.
</field>
-
+
<field id="MFF_IP_FRAG" title="IPv4/v6 Fragment Bitmask">
<p>
Specifies what kinds of IP fragments or non-fragments to match. The
@@ -4180,6 +4159,115 @@ r r c c c.
<field id="MFF_ARP_THA" title="ARP Target Ethernet Address"/>
</group>
+ <group title="Layer 3: NSH">
+ <p>
+ Service functions are widely deployed and essential in many networks.
+ These service functions provide a range of features such as security,
+ WAN acceleration, and server load balancing. Service functions may
+ be instantiated at different points in the network infrastructure
+ such as the wide area network, data center, and so forth.
+ </p>
+
+ <p>
+ Prior to development of the SFC architecture [RFC 7665] and the
+ protocol specified in this document, current service function
+ deployment models have been relatively static and bound to topology
+ for insertion and policy selection. Furthermore, they do not adapt
+ well to elastic service environments enabled by virtualization.
+ </p>
+
+ <p>
+ New data center network and cloud architectures require more flexible
+ service function deployment models. Additionally, the transition to
+ virtual platforms demands an agile service insertion model that
+ supports dynamic and elastic service delivery. Specifically, the
+ following functions are necessary:
+ </p>
+
+ <p>
+ 1. The movement of service functions and application workloads in
+ the network.
+ </p>
+
+ <p>
+ 2. The ability to easily bind service policy to granular
+ information, such as per-subscriber state.
+ </p>
+
+ <p>
+ 3. The capability to steer traffic to the requisite service
+ function(s).
+ </p>
+
+ <p>
+ The Network Service Header (NSH) specification defines a new data
+ plane protocol, which is an encapsulation for service function
+ chains. The NSH is designed to encapsulate an original packet or
+ frame, and in turn be encapsulated by an outer transport
+ encapsulation (which is used to deliver the NSH to NSH-aware network
+ elements), as shown in Figure 1:
+ </p>
+
+ <pre>
+
+ +------------------------------+
+ | Transport Encapsulation |
+ +------------------------------+
+ | Network Service Header (NSH) |
+ +------------------------------+
+ | Original Packet / Frame |
+ +------------------------------+
+
+ Figure 1: Network Service Header Encapsulation
+ </pre>
+
+ <p>
+ The NSH is composed of the following elements:
+ </p>
+
+ <p>
+ 1. Service Function Path identification.
+ </p>
+
+ <p>
+ 2. Indication of location within a Service Function Path.
+ </p>
+
+ <p>
+ 3. Optional, per packet metadata (fixed length or variable).
+ </p>
+
+ <p>
+ [RFC 7665] provides an overview of a service chaining architecture
+ that clearly defines the roles of the various elements and the scope
+ of a service function chaining encapsulation. Figure 3 of [RFC 7665]
+ depicts the SFC architectural components after classification. The
+ NSH is the SFC encapsulation referenced in [RFC 7665].
+ </p>
+
+ <field id="MFF_NSH_FLAGS"
+ title="flags field (2 bits)"/>
+ <field id="MFF_NSH_TTL"
+ title="TTL field (6 bits)"/>
+ <field id="MFF_NSH_MDTYPE"
+ title="mdtype field (8 bits)"/>
+ <field id="MFF_NSH_NP"
+ title="np (next protocol) field (8 bits)"/>
+ <field id="MFF_NSH_SPI"
+ title="spi (service path identifier) field (24 bits)"/>
+ <field id="MFF_NSH_SI"
+ title="si (service index) field (8 bits)"/>
+ <field id="MFF_NSH_C1"
+ title="c1 (Network Platform Context) field (32 bits)"/>
+ <field id="MFF_NSH_C2"
+ title="c2 (Network Shared Context) field (32 bits)"/>
+ <field id="MFF_NSH_C3"
+ title="c3 (Service Platform Context) field (32 bits)"/>
+ <field id="MFF_NSH_C4"
+ title="c4 (Service Shared Context) field (32 bits)"/>
+ </group>
+
+
<group title="Layer 4: TCP, UDP, and SCTP">
<p>
For matching purposes, no distinction is made whether these protocols are
@@ -4567,6 +4655,13 @@ r r c c c.
Layer 3 Networks, '' <url href="https://tools.ietf.org/html/rfc7348"/>.
</dd>
+ <dt>RFC 7665</dt>
+ <dd>
+ J. Halpern, Ed. and C. Pignataro, Ed.,
+ ``Service Function Chaining (SFC) Architecture,''
+ <url href="https://tools.ietf.org/html/rfc7665"/>.
+ </dd>
+
<dt>Srinivasan</dt>
<dd>
V. Srinivasan, S. Suriy, and G. Varghese, ``Packet
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 8f2a442e9..aa7691ae9 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -1022,6 +1022,7 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
const struct flow *flow = &match->flow;
const size_t start_len = b->size;
ovs_be16 dl_type = get_dl_type(flow);
+ ovs_be32 spi_mask;
int match_len;
int i;
@@ -1157,13 +1158,22 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
/* Network Service Header */
nxm_put_8m(&ctx, MFF_NSH_FLAGS, oxm, flow->nsh.flags,
match->wc.masks.nsh.flags);
+ nxm_put_8m(&ctx, MFF_NSH_TTL, oxm, flow->nsh.ttl,
+ match->wc.masks.nsh.ttl);
nxm_put_8m(&ctx, MFF_NSH_MDTYPE, oxm, flow->nsh.mdtype,
match->wc.masks.nsh.mdtype);
nxm_put_8m(&ctx, MFF_NSH_NP, oxm, flow->nsh.np,
match->wc.masks.nsh.np);
- nxm_put_32m(&ctx, MFF_NSH_SPI, oxm, flow->nsh.spi,
- match->wc.masks.nsh.spi);
- nxm_put_8m(&ctx, MFF_NSH_SI, oxm, flow->nsh.si, match->wc.masks.nsh.si);
+ spi_mask = nsh_path_hdr_to_spi(match->wc.masks.nsh.path_hdr);
+ if (spi_mask == htonl(NSH_SPI_MASK >> NSH_SPI_SHIFT)) {
+ spi_mask = OVS_BE32_MAX;
+ }
+ nxm_put_32m(&ctx, MFF_NSH_SPI, oxm,
+ nsh_path_hdr_to_spi(flow->nsh.path_hdr),
+ spi_mask);
+ nxm_put_8m(&ctx, MFF_NSH_SI, oxm,
+ nsh_path_hdr_to_si(flow->nsh.path_hdr),
+ nsh_path_hdr_to_si(match->wc.masks.nsh.path_hdr));
for (int i = 0; i < 4; i++) {
nxm_put_32m(&ctx, MFF_NSH_C1 + i, oxm, flow->nsh.context[i],
match->wc.masks.nsh.context[i]);
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index 7f9d4198c..c6803642a 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -274,19 +274,16 @@ odp_set_nd(struct dp_packet *packet, const struct ovs_key_nd *key,
/* Set the NSH header. Assumes the NSH header is present and matches the
* MD format of the key. The slow path must take case of that. */
static void
-odp_set_nsh(struct dp_packet *packet, const struct flow_nsh *key,
- const struct flow_nsh *mask)
+odp_set_nsh(struct dp_packet *packet, const struct ovs_key_nsh *key,
+ const struct ovs_key_nsh *mask)
{
struct nsh_hdr *nsh = dp_packet_l3(packet);
uint8_t mdtype = nsh_md_type(nsh);
ovs_be32 path_hdr;
if (!mask) {
- nsh->ver_flags_ttl_len = htons(key->flags << NSH_FLAGS_SHIFT) |
- (nsh->ver_flags_ttl_len & ~htons(NSH_FLAGS_MASK));
- path_hdr = htonl((ntohl(key->spi) << NSH_SPI_SHIFT) |
- key->si);
- put_16aligned_be32(&nsh->path_hdr, path_hdr);
+ nsh_set_flags_and_ttl(nsh, key->flags, key->ttl);
+ put_16aligned_be32(&nsh->path_hdr, key->path_hdr);
switch (mdtype) {
case NSH_M_TYPE1:
for (int i = 0; i < 4; i++) {
@@ -299,22 +296,25 @@ odp_set_nsh(struct dp_packet *packet, const struct flow_nsh *key,
break;
}
} else {
- uint8_t flags = (ntohs(nsh->ver_flags_ttl_len) & NSH_FLAGS_MASK) >>
- NSH_FLAGS_SHIFT;
+ uint8_t flags = nsh_get_flags(nsh);
+ uint8_t ttl = nsh_get_ttl(nsh);
+
flags = key->flags | (flags & ~mask->flags);
- nsh->ver_flags_ttl_len = htons(flags << NSH_FLAGS_SHIFT) |
- (nsh->ver_flags_ttl_len & ~htons(NSH_FLAGS_MASK));
+ ttl = key->ttl | (ttl & ~mask->ttl);
+ nsh_set_flags_and_ttl(nsh, flags, ttl);
- path_hdr = get_16aligned_be32(&nsh->path_hdr);
- uint32_t spi = (ntohl(path_hdr) & NSH_SPI_MASK) >> NSH_SPI_SHIFT;
- uint8_t si = (ntohl(path_hdr) & NSH_SI_MASK) >> NSH_SI_SHIFT;
- uint32_t spi_mask = ntohl(mask->spi);
+ uint32_t spi = ntohl(nsh_get_spi(nsh));
+ uint8_t si = nsh_get_si(nsh);
+ uint32_t spi_mask = nsh_path_hdr_to_spi_uint32(mask->path_hdr);
+ uint8_t si_mask = nsh_path_hdr_to_si(mask->path_hdr);
if (spi_mask == 0x00ffffff) {
spi_mask = UINT32_MAX;
}
- spi = ntohl(key->spi) | (spi & ~spi_mask);
- si = key->si | (si & ~mask->si);
- path_hdr = htonl((spi << NSH_SPI_SHIFT) | si);
+ spi = nsh_path_hdr_to_spi_uint32(key->path_hdr) | (spi & ~spi_mask);
+ si = nsh_path_hdr_to_si(key->path_hdr) | (si & ~si_mask);
+ path_hdr = nsh_get_path_hdr(nsh);
+ nsh_path_hdr_set_spi(&path_hdr, htonl(spi));
+ nsh_path_hdr_set_si(&path_hdr, si);
put_16aligned_be32(&nsh->path_hdr, path_hdr);
switch (mdtype) {
case NSH_M_TYPE1:
@@ -359,7 +359,7 @@ odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a)
break;
case OVS_KEY_ATTR_NSH: {
- struct flow_nsh nsh;
+ struct ovs_key_nsh nsh;
odp_nsh_key_from_attr(a, &nsh);
odp_set_nsh(packet, &nsh, NULL);
break;
@@ -490,7 +490,7 @@ odp_execute_masked_set_action(struct dp_packet *packet,
break;
case OVS_KEY_ATTR_NSH: {
- struct flow_nsh nsh, nsh_mask;
+ struct ovs_key_nsh nsh, nsh_mask;
struct {
struct nlattr nla;
uint8_t data[sizeof(struct ovs_nsh_key_base) + NSH_CTX_HDRS_MAX_LEN
diff --git a/lib/odp-util.c b/lib/odp-util.c
index f8c84e173..195f2d4f5 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -246,12 +246,13 @@ static void
format_nsh_key(struct ds *ds, const struct ovs_key_nsh *key)
{
ds_put_format(ds, "flags=%d", key->flags);
+ ds_put_format(ds, "ttl=%d", key->ttl);
ds_put_format(ds, ",mdtype=%d", key->mdtype);
ds_put_format(ds, ",np=%d", key->np);
ds_put_format(ds, ",spi=0x%x",
- (ntohl(key->path_hdr) & NSH_SPI_MASK) >> NSH_SPI_SHIFT);
+ nsh_path_hdr_to_spi_uint32(key->path_hdr));
ds_put_format(ds, ",si=%d",
- (ntohl(key->path_hdr) & NSH_SI_MASK) >> NSH_SI_SHIFT);
+ nsh_path_hdr_to_si(key->path_hdr));
switch (key->mdtype) {
case NSH_M_TYPE1:
@@ -311,17 +312,16 @@ format_nsh_key_mask(struct ds *ds, const struct ovs_key_nsh *key,
format_nsh_key(ds, key);
} else {
bool first = true;
- uint32_t spi = (ntohl(key->path_hdr) & NSH_SPI_MASK) >> NSH_SPI_SHIFT;
- uint32_t spi_mask = (ntohl(mask->path_hdr) & NSH_SPI_MASK) >>
- NSH_SPI_SHIFT;
- if (spi_mask == 0x00ffffff) {
+ uint32_t spi = nsh_path_hdr_to_spi_uint32(key->path_hdr);
+ uint32_t spi_mask = nsh_path_hdr_to_spi_uint32(mask->path_hdr);
+ if (spi_mask == (NSH_SPI_MASK >> NSH_SPI_SHIFT)) {
spi_mask = UINT32_MAX;
}
- uint8_t si = (ntohl(key->path_hdr) & NSH_SI_MASK) >> NSH_SI_SHIFT;
- uint8_t si_mask = (ntohl(mask->path_hdr) & NSH_SI_MASK) >>
- NSH_SI_SHIFT;
+ uint8_t si = nsh_path_hdr_to_si(key->path_hdr);
+ uint8_t si_mask = nsh_path_hdr_to_si(mask->path_hdr);
format_uint8_masked(ds, &first, "flags", key->flags, mask->flags);
+ format_uint8_masked(ds, &first, "ttl", key->ttl, mask->ttl);
format_uint8_masked(ds, &first, "mdtype", key->mdtype, mask->mdtype);
format_uint8_masked(ds, &first, "np", key->np, mask->np);
format_be32_masked(ds, &first, "spi", htonl(spi), htonl(spi_mask));
@@ -342,13 +342,14 @@ format_odp_push_nsh_action(struct ds *ds,
const struct nsh_hdr *nsh_hdr)
{
size_t mdlen = nsh_hdr_len(nsh_hdr) - NSH_BASE_HDR_LEN;
- uint32_t path_hdr = ntohl(get_16aligned_be32(&nsh_hdr->path_hdr));
- uint32_t spi = (path_hdr & NSH_SPI_MASK) >> NSH_SPI_SHIFT;
- uint8_t si = (path_hdr & NSH_SI_MASK) >> NSH_SI_SHIFT;
+ uint32_t spi = ntohl(nsh_get_spi(nsh_hdr));
+ uint8_t si = nsh_get_si(nsh_hdr);
uint8_t flags = nsh_get_flags(nsh_hdr);
+ uint8_t ttl = nsh_get_ttl(nsh_hdr);
ds_put_cstr(ds, "push_nsh(");
ds_put_format(ds, "flags=%d", flags);
+ ds_put_format(ds, ",ttl=%d", ttl);
ds_put_format(ds, ",mdtype=%d", nsh_hdr->md_type);
ds_put_format(ds, ",np=%d", nsh_hdr->next_proto);
ds_put_format(ds, ",spi=0x%x", spi);
@@ -1826,7 +1827,7 @@ find_end:
}
static void
-nsh_key_to_attr(struct ofpbuf *buf, const struct flow_nsh *nsh,
+nsh_key_to_attr(struct ofpbuf *buf, const struct ovs_key_nsh *nsh,
uint8_t * metadata, size_t md_size,
bool is_mask)
{
@@ -1834,10 +1835,10 @@ nsh_key_to_attr(struct ofpbuf *buf, const struct flow_nsh *nsh,
struct ovs_nsh_key_base base;
base.flags = nsh->flags;
+ base.ttl = nsh->ttl;
base.mdtype = nsh->mdtype;
base.np = nsh->np;
- base.path_hdr = htonl((ntohl(nsh->spi) << NSH_SPI_SHIFT) |
- nsh->si);
+ base.path_hdr = nsh->path_hdr;
nsh_key_ofs = nl_msg_start_nested(buf, OVS_KEY_ATTR_NSH);
nl_msg_put_unspec(buf, OVS_NSH_KEY_ATTR_BASE, &base, sizeof base);
@@ -1872,8 +1873,9 @@ parse_odp_push_nsh_action(const char *s, struct ofpbuf *actions)
int n = 0;
int ret = 0;
uint32_t spi = 0;
+ uint8_t si = 255;
uint32_t cd;
- struct flow_nsh nsh;
+ struct ovs_key_nsh nsh;
uint8_t metadata[NSH_CTX_HDRS_MAX_LEN];
uint8_t md_size = 0;
@@ -1884,10 +1886,10 @@ parse_odp_push_nsh_action(const char *s, struct ofpbuf *actions)
/* The default is NSH_M_TYPE1 */
nsh.flags = 0;
+ nsh.ttl = 63;
nsh.mdtype = NSH_M_TYPE1;
nsh.np = NSH_P_ETHERNET;
- nsh.spi = 0;
- nsh.si = 255;
+ nsh.path_hdr = nsh_spi_si_to_path_hdr(0, 255);
memset(nsh.context, 0, NSH_M_TYPE1_MDLEN);
for (;;) {
@@ -1899,6 +1901,9 @@ parse_odp_push_nsh_action(const char *s, struct ofpbuf *actions)
if (ovs_scan_len(s, &n, "flags=%"SCNi8, &nsh.flags)) {
continue;
}
+ if (ovs_scan_len(s, &n, "ttl=%"SCNi8, &nsh.ttl)) {
+ continue;
+ }
if (ovs_scan_len(s, &n, "mdtype=%"SCNi8, &nsh.mdtype)) {
switch (nsh.mdtype) {
case NSH_M_TYPE1:
@@ -1918,10 +1923,9 @@ parse_odp_push_nsh_action(const char *s, struct ofpbuf *actions)
continue;
}
if (ovs_scan_len(s, &n, "spi=0x%"SCNx32, &spi)) {
- nsh.spi = htonl(spi);
continue;
}
- if (ovs_scan_len(s, &n, "si=%"SCNi8, &nsh.si)) {
+ if (ovs_scan_len(s, &n, "si=%"SCNi8, &si)) {
continue;
}
if (nsh.mdtype == NSH_M_TYPE1) {
@@ -1966,6 +1970,7 @@ parse_odp_push_nsh_action(const char *s, struct ofpbuf *actions)
}
out:
if (ret >= 0) {
+ nsh.path_hdr = nsh_spi_si_to_path_hdr(spi, si);
size_t offset = nl_msg_start_nested(actions, OVS_ACTION_ATTR_PUSH_NSH);
nsh_key_to_attr(actions, &nsh, metadata, md_size, false);
nl_msg_end_nested(actions, offset);
@@ -2393,6 +2398,7 @@ odp_nsh_hdr_from_attr(const struct nlattr *attr,
const struct nlattr *a;
bool unknown = false;
uint8_t flags = 0;
+ uint8_t ttl = 63;
size_t mdlen = 0;
bool has_md1 = false;
bool has_md2 = false;
@@ -2414,6 +2420,7 @@ odp_nsh_hdr_from_attr(const struct nlattr *attr,
nsh_hdr->md_type = base->mdtype;
put_16aligned_be32(&nsh_hdr->path_hdr, base->path_hdr);
flags = base->flags;
+ ttl = base->ttl;
break;
}
case OVS_NSH_KEY_ATTR_MD1: {
@@ -2457,14 +2464,13 @@ odp_nsh_hdr_from_attr(const struct nlattr *attr,
}
/* nsh header length = NSH_BASE_HDR_LEN + mdlen */
- nsh_hdr->ver_flags_ttl_len = htons(flags << NSH_FLAGS_SHIFT |
- (NSH_BASE_HDR_LEN + mdlen) >> 2);
+ nsh_set_flags_ttl_len(nsh_hdr, flags, ttl, NSH_BASE_HDR_LEN + mdlen);
return ODP_FIT_PERFECT;
}
enum odp_key_fitness
-odp_nsh_key_from_attr(const struct nlattr *attr, struct flow_nsh *nsh)
+odp_nsh_key_from_attr(const struct nlattr *attr, struct ovs_key_nsh *nsh)
{
unsigned int left;
const struct nlattr *a;
@@ -2485,11 +2491,10 @@ odp_nsh_key_from_attr(const struct nlattr *attr, struct flow_nsh *nsh)
case OVS_NSH_KEY_ATTR_BASE: {
const struct ovs_nsh_key_base *base = nl_attr_get(a);
nsh->flags = base->flags;
+ nsh->ttl = base->ttl;
nsh->mdtype = base->mdtype;
nsh->np = base->np;
- nsh->spi = htonl((ntohl(base->path_hdr) & NSH_SPI_MASK) >>
- NSH_SPI_SHIFT);
- nsh->si = (ntohl(base->path_hdr) & NSH_SI_MASK) >> NSH_SI_SHIFT;
+ nsh->path_hdr = base->path_hdr;
break;
}
case OVS_NSH_KEY_ATTR_MD1: {
@@ -3238,15 +3243,17 @@ format_odp_nsh_attr(const struct nlattr *attr, const struct nlattr *mask_attr,
case OVS_NSH_KEY_ATTR_UNSPEC:
break;
case OVS_NSH_KEY_ATTR_BASE: {
- const struct ovs_nsh_key_base * base = nl_attr_get(a);
- const struct ovs_nsh_key_base * base_mask
+ const struct ovs_nsh_key_base *base = nl_attr_get(a);
+ const struct ovs_nsh_key_base *base_mask
= ma ? nl_attr_get(ma) : NULL;
nsh.flags = base->flags;
+ nsh.ttl = base->ttl;
nsh.mdtype = base->mdtype;
nsh.np = base->np;
nsh.path_hdr = base->path_hdr;
if (base_mask) {
nsh_mask.flags = base_mask->flags;
+ nsh_mask.ttl = base_mask->ttl;
nsh_mask.mdtype = base_mask->mdtype;
nsh_mask.np = base_mask->np;
nsh_mask.path_hdr = base_mask->path_hdr;
@@ -3254,8 +3261,8 @@ format_odp_nsh_attr(const struct nlattr *attr, const struct nlattr *mask_attr,
break;
}
case OVS_NSH_KEY_ATTR_MD1: {
- const struct ovs_nsh_key_md1 * md1 = nl_attr_get(a);
- const struct ovs_nsh_key_md1 * md1_mask
+ const struct ovs_nsh_key_md1 *md1 = nl_attr_get(a);
+ const struct ovs_nsh_key_md1 *md1_mask
= ma ? nl_attr_get(ma) : NULL;
memcpy(nsh.context, md1->context, sizeof md1->context);
if (md1_mask) {
@@ -4863,7 +4870,9 @@ parse_odp_nsh_key_mask_attr(const char *s, struct ofpbuf *key,
if (strncmp(s, "nsh(", 4) == 0) {
const char *start = s;
int len;
- struct flow_nsh skey, smask;
+ struct ovs_key_nsh skey, smask;
+ uint32_t spi = 0, spi_mask = 0;
+ uint8_t si = 0, si_mask = 0;
s += 4;
@@ -4904,7 +4913,7 @@ parse_odp_nsh_key_mask_attr(const char *s, struct ofpbuf *key,
if (strncmp(s, "spi=", 4) == 0) {
s += 4;
- len = scan_be32(s, &skey.spi, mask ? &smask.spi : NULL);
+ len = scan_u32(s, &spi, mask ? &spi_mask : NULL);
if (len == 0) {
return -EINVAL;
}
@@ -4914,7 +4923,7 @@ parse_odp_nsh_key_mask_attr(const char *s, struct ofpbuf *key,
if (strncmp(s, "si=", 3) == 0) {
s += 3;
- len = scan_u8(s, &skey.si, mask ? &smask.si : NULL);
+ len = scan_u8(s, &si, mask ? &si_mask : NULL);
if (len == 0) {
return -EINVAL;
}
@@ -4970,6 +4979,9 @@ parse_odp_nsh_key_mask_attr(const char *s, struct ofpbuf *key,
return -EINVAL;
}
+ skey.path_hdr = nsh_spi_si_to_path_hdr(spi, si);
+ smask.path_hdr = nsh_spi_si_to_path_hdr(spi_mask, si_mask);
+
nsh_key_to_attr(key, &skey, NULL, 0, false);
if (mask) {
nsh_key_to_attr(mask, &smask, NULL, 0, true);
@@ -7031,59 +7043,29 @@ commit_set_nw_action(const struct flow *flow, struct flow *base,
return 0;
}
-static void
+static inline void
get_nsh_key(const struct flow *flow, struct ovs_key_nsh *nsh, bool is_mask)
{
- nsh->flags = flow->nsh.flags;
- nsh->mdtype = flow->nsh.mdtype;
- nsh->np = flow->nsh.np;
- nsh->path_hdr = htonl((ntohl(flow->nsh.spi) << NSH_SPI_SHIFT) |
- flow->nsh.si);
- if (is_mask) {
- for (int i = 0; i < 4; i++) {
- nsh->context[i] = flow->nsh.context[i];
- }
- } else {
- switch (nsh->mdtype) {
- case NSH_M_TYPE1:
- for (int i = 0; i < 4; i++) {
- nsh->context[i] = flow->nsh.context[i];
- }
- break;
- case NSH_M_TYPE2:
- default:
- /* No match support for other MD formats yet. */
- break;
+ *nsh = flow->nsh;
+ if (!is_mask) {
+ if (nsh->mdtype != NSH_M_TYPE1) {
+ memset(nsh->context, 0, sizeof(nsh->context));
}
}
}
-static void
+static inline void
put_nsh_key(const struct ovs_key_nsh *nsh, struct flow *flow,
bool is_mask OVS_UNUSED)
{
- flow->nsh.flags = nsh->flags;
- flow->nsh.mdtype = nsh->mdtype;
- flow->nsh.np = nsh->np;
- flow->nsh.spi = htonl((ntohl(nsh->path_hdr) & NSH_SPI_MASK) >>
- NSH_SPI_SHIFT);
- flow->nsh.si = (ntohl(nsh->path_hdr) & NSH_SI_MASK) >> NSH_SI_SHIFT;
- switch (nsh->mdtype) {
- case NSH_M_TYPE1:
- for (int i = 0; i < 4; i++) {
- flow->nsh.context[i] = nsh->context[i];
- }
- break;
- case NSH_M_TYPE2:
- default:
- /* No match support for other MD formats yet. */
- memset(flow->nsh.context, 0, sizeof flow->nsh.context);
- break;
+ flow->nsh = *nsh;
+ if (flow->nsh.mdtype != NSH_M_TYPE1) {
+ memset(flow->nsh.context, 0, sizeof(flow->nsh.context));
}
}
static bool
-commit_nsh(const struct flow_nsh * flow_nsh, bool use_masked_set,
+commit_nsh(const struct ovs_key_nsh * flow_nsh, bool use_masked_set,
const struct ovs_key_nsh *key, struct ovs_key_nsh *base,
struct ovs_key_nsh *mask, size_t size,
struct ofpbuf *odp_actions)
@@ -7109,11 +7091,13 @@ commit_nsh(const struct flow_nsh * flow_nsh, bool use_masked_set,
OVS_ACTION_ATTR_SET_MASKED);
nsh_base.flags = key->flags;
+ nsh_base.ttl = key->ttl;
nsh_base.mdtype = key->mdtype;
nsh_base.np = key->np;
nsh_base.path_hdr = key->path_hdr;
nsh_base_mask.flags = mask->flags;
+ nsh_base_mask.ttl = mask->ttl;
nsh_base_mask.mdtype = mask->mdtype;
nsh_base_mask.np = mask->np;
nsh_base_mask.path_hdr = mask->path_hdr;
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 028c9e37c..e4760956d 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -158,7 +158,7 @@ struct odputil_keybuf {
enum odp_key_fitness odp_tun_key_from_attr(const struct nlattr *,
struct flow_tnl *);
enum odp_key_fitness odp_nsh_key_from_attr(const struct nlattr *,
- struct flow_nsh *);
+ struct ovs_key_nsh *);
enum odp_key_fitness odp_nsh_hdr_from_attr(const struct nlattr *,
struct nsh_hdr *, size_t size);