summaryrefslogtreecommitdiff
path: root/lib/odp-execute.c
diff options
context:
space:
mode:
authorJan Scheurich <jan.scheurich@ericsson.com>2017-08-05 13:41:08 +0800
committerBen Pfaff <blp@ovn.org>2017-08-07 11:26:09 -0700
commit3d2fbd70bda514f7327970b859663f34f994290c (patch)
tree5a5fb77fbc30f598c56c5af1d666a70bf815a796 /lib/odp-execute.c
parent05f282c2e16126577de7704b16f9dd591b927904 (diff)
downloadopenvswitch-3d2fbd70bda514f7327970b859663f34f994290c.tar.gz
userspace: Add support for NSH MD1 match fields
This patch adds support for NSH packet header fields to the OVS control plane and the userspace datapath. Initially we support the fields of the NSH base header as defined in https://www.ietf.org/id/draft-ietf-sfc-nsh-13.txt and the fixed context headers specified for metadata format MD1. The variable length MD2 format is parsed but the TLV context headers are not yet available for matching. The NSH fields are modelled as experimenter fields with the dedicated experimenter class 0x005ad650 proposed for NSH in ONF. The following fields are defined: NXOXM code ofctl name Size Comment ===================================================================== NXOXM_NSH_FLAGS nsh_flags 8 Bits 2-9 of 1st NSH word (0x005ad650,1) NXOXM_NSH_MDTYPE nsh_mdtype 8 Bits 16-23 (0x005ad650,2) NXOXM_NSH_NEXTPROTO nsh_np 8 Bits 24-31 (0x005ad650,3) NXOXM_NSH_SPI nsh_spi 24 Bits 0-23 of 2nd NSH word (0x005ad650,4) NXOXM_NSH_SI nsh_si 8 Bits 24-31 (0x005ad650,5) NXOXM_NSH_C1 nsh_c1 32 Maskable, nsh_mdtype==1 (0x005ad650,6) NXOXM_NSH_C2 nsh_c2 32 Maskable, nsh_mdtype==1 (0x005ad650,7) NXOXM_NSH_C3 nsh_c3 32 Maskable, nsh_mdtype==1 (0x005ad650,8) NXOXM_NSH_C4 nsh_c4 32 Maskable, nsh_mdtype==1 (0x005ad650,9) Co-authored-by: Johnson Li <johnson.li@intel.com> Signed-off-by: Yi Yang <yi.y.yang@intel.com> Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'lib/odp-execute.c')
-rw-r--r--lib/odp-execute.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index 03120bf06..e631c6836 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -270,6 +270,58 @@ 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 ovs_key_nsh *key,
+ const struct ovs_key_nsh *mask)
+{
+ struct nsh_hdr *nsh = dp_packet_l3(packet);
+
+ if (!mask) {
+ nsh->ver_flags_len = htons(key->flags << NSH_FLAGS_SHIFT) |
+ (nsh->ver_flags_len & ~htons(NSH_FLAGS_MASK));
+ put_16aligned_be32(&nsh->path_hdr, key->path_hdr);
+ switch (nsh->md_type) {
+ case NSH_M_TYPE1:
+ for (int i = 0; i < 4; i++) {
+ put_16aligned_be32(&nsh->md1.c[i], key->c[i]);
+ }
+ break;
+ case NSH_M_TYPE2:
+ /* TODO */
+ break;
+ default:
+ OVS_NOT_REACHED();
+ }
+ } else {
+ uint8_t flags = (ntohs(nsh->ver_flags_len) & NSH_FLAGS_MASK) >>
+ NSH_FLAGS_SHIFT;
+ flags = key->flags | (flags & ~mask->flags);
+ nsh->ver_flags_len = htons(flags << NSH_FLAGS_SHIFT) |
+ (nsh->ver_flags_len & ~htons(NSH_FLAGS_MASK));
+
+ ovs_be32 path_hdr = get_16aligned_be32(&nsh->path_hdr);
+ path_hdr = key->path_hdr | (path_hdr & ~mask->path_hdr);
+ put_16aligned_be32(&nsh->path_hdr, path_hdr);
+ switch (nsh->md_type) {
+ case NSH_M_TYPE1:
+ for (int i = 0; i < 4; i++) {
+ ovs_be32 p = get_16aligned_be32(&nsh->md1.c[i]);
+ ovs_be32 k = key->c[i];
+ ovs_be32 m = mask->c[i];
+ put_16aligned_be32(&nsh->md1.c[i], k | (p & ~m));
+ }
+ break;
+ case NSH_M_TYPE2:
+ /* TODO */
+ break;
+ default:
+ OVS_NOT_REACHED();
+ }
+ }
+}
+
static void
odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a)
{
@@ -295,6 +347,10 @@ odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a)
odp_eth_set_addrs(packet, nl_attr_get(a), NULL);
break;
+ case OVS_KEY_ATTR_NSH:
+ odp_set_nsh(packet, nl_attr_get(a), NULL);
+ break;
+
case OVS_KEY_ATTR_IPV4:
ipv4_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv4));
packet_set_ipv4(packet, ipv4_key->ipv4_src,
@@ -419,6 +475,11 @@ odp_execute_masked_set_action(struct dp_packet *packet,
get_mask(a, struct ovs_key_ethernet));
break;
+ case OVS_KEY_ATTR_NSH:
+ odp_set_nsh(packet, nl_attr_get(a),
+ get_mask(a, struct ovs_key_nsh));
+ break;
+
case OVS_KEY_ATTR_IPV4:
odp_set_ipv4(packet, nl_attr_get(a),
get_mask(a, struct ovs_key_ipv4));