[ovs-dev] [mpls v2 2/2] Add OpenFlow support for matching multiple MPLS labels at once.
Ben Pfaff
blp at nicira.com
Sun Dec 29 07:50:45 UTC 2013
This is an OpenFlow extension that might be useful. I don't know how MPLS
works in practice well enough to judge.
Signed-off-by: Ben Pfaff <blp at nicira.com>
---
include/openflow/nicira-ext.h | 38 ++++++++++++++++++
lib/meta-flow.c | 86 ++++++++++++++++++++++++++++++++++++++++-
lib/meta-flow.h | 5 +++
lib/nx-match.c | 38 ++++++++++++++----
4 files changed, 157 insertions(+), 10 deletions(-)
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index 22939f4..3746484 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -1803,6 +1803,44 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24);
#define NXM_NX_TCP_FLAGS NXM_HEADER (0x0001, 34, 2)
#define NXM_NX_TCP_FLAGS_W NXM_HEADER_W(0x0001, 34, 2)
+/* MPLS LSEs.
+ *
+ * NXM_NX_MPLS_LSE0 is the outermost label.
+ *
+ * Prereqs:
+ * NXM_OF_ETH_TYPE must be either 0x8847 or 0x8848.
+ * For NXM_NX_MPLS_LSE1 and later, NXM_NX_MPLS_LSE0 must match a value of 0
+ * in the BOS bit.
+ * For NXM_NX_MPLS_LSE2 and later, NXM_NX_MPLS_LSE1 must match a value of 0
+ * in the BOS bit.
+ * For NXM_NX_MPLS_LSE3 and later, NXM_NX_MPLS_LSE2 must match a value of 0
+ * in the BOS bit.
+ * and so on...
+ *
+ * Format:
+ * 32-bit integer in network byte order. Space is reserved for up to
+ * 8 labels, but switches may implement fewer.
+ *
+ * Masking: Fully maskable.
+ */
+#define NXM_NX_MPLS_LSE0 NXM_HEADER (0x0001, 35, 4)
+#define NXM_NX_MPLS_LSE0_W NXM_HEADER_W(0x0001, 35, 4)
+#define NXM_NX_MPLS_LSE1 NXM_HEADER (0x0001, 36, 4)
+#define NXM_NX_MPLS_LSE1_W NXM_HEADER_W(0x0001, 36, 4)
+#define NXM_NX_MPLS_LSE2 NXM_HEADER (0x0001, 37, 4)
+#define NXM_NX_MPLS_LSE2_W NXM_HEADER_W(0x0001, 37, 4)
+#define NXM_NX_MPLS_LSE3 NXM_HEADER (0x0001, 38, 4)
+#define NXM_NX_MPLS_LSE3_W NXM_HEADER_W(0x0001, 38, 4)
+#define NXM_NX_MPLS_LSE4 NXM_HEADER (0x0001, 39, 4)
+#define NXM_NX_MPLS_LSE4_W NXM_HEADER_W(0x0001, 39, 4)
+#define NXM_NX_MPLS_LSE5 NXM_HEADER (0x0001, 40, 4)
+#define NXM_NX_MPLS_LSE5_W NXM_HEADER_W(0x0001, 40, 4)
+#define NXM_NX_MPLS_LSE6 NXM_HEADER (0x0001, 41, 4)
+#define NXM_NX_MPLS_LSE6_W NXM_HEADER_W(0x0001, 41, 4)
+#define NXM_NX_MPLS_LSE7 NXM_HEADER (0x0001, 42, 4)
+#define NXM_NX_MPLS_LSE8_W NXM_HEADER_W(0x0001, 42, 4)
+
+
/* ## --------------------- ## */
/* ## Requests and replies. ## */
/* ## --------------------- ## */
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index a168222..a10492c 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -370,6 +370,42 @@ const struct mf_field mf_fields[MFF_N_IDS] = {
OFPUTIL_P_NXM_OXM_ANY,
OFPUTIL_P_NONE,
-1,
+ }, {
+ MFF_MPLS_LSE0, "mpls_lse0", NULL,
+ MF_FIELD_SIZES(be32),
+ MFM_FULLY,
+ MFS_HEXADECIMAL,
+ MFP_MPLS,
+ false,
+ NXM_NX_MPLS_LSE0, "NXM_NX_MPLS_LSE0",
+ NXM_NX_MPLS_LSE0, "NXM_NX_MPLS_LSE0",
+ OFPUTIL_P_NXM_OXM_ANY,
+ OFPUTIL_P_NONE,
+ -1,
+ }, {
+ MFF_MPLS_LSE1, "mpls_lse1", NULL,
+ MF_FIELD_SIZES(be32),
+ MFM_FULLY,
+ MFS_HEXADECIMAL,
+ MFP_MPLS1,
+ false,
+ NXM_NX_MPLS_LSE1, "NXM_NX_MPLS_LSE1",
+ NXM_NX_MPLS_LSE1, "NXM_NX_MPLS_LSE1",
+ OFPUTIL_P_NXM_OXM_ANY,
+ OFPUTIL_P_NONE,
+ -1,
+ }, {
+ MFF_MPLS_LSE2, "mpls_lse2", NULL,
+ MF_FIELD_SIZES(be32),
+ MFM_FULLY,
+ MFS_HEXADECIMAL,
+ MFP_MPLS2,
+ false,
+ NXM_NX_MPLS_LSE2, "NXM_NX_MPLS_LSE2",
+ NXM_NX_MPLS_LSE2, "NXM_NX_MPLS_LSE2",
+ OFPUTIL_P_NXM_OXM_ANY,
+ OFPUTIL_P_NONE,
+ -1,
},
/* ## -- ## */
@@ -928,9 +964,13 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
case MFF_MPLS_LABEL:
return !(wc->masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK));
case MFF_MPLS_TC:
- return !(wc->masks.mpls_lse[1] & htonl(MPLS_TC_MASK));
+ return !(wc->masks.mpls_lse[0] & htonl(MPLS_TC_MASK));
case MFF_MPLS_BOS:
- return !(wc->masks.mpls_lse[2] & htonl(MPLS_BOS_MASK));
+ return !(wc->masks.mpls_lse[0] & htonl(MPLS_BOS_MASK));
+ case MFF_MPLS_LSE0:
+ case MFF_MPLS_LSE1:
+ case MFF_MPLS_LSE2:
+ return !wc->masks.mpls_lse[mf->id - MFF_MPLS_LSE0];
case MFF_IPV4_SRC:
return !wc->masks.nw_src;
@@ -1052,6 +1092,13 @@ mf_are_prereqs_ok(const struct mf_field *mf, const struct flow *flow)
return (flow->vlan_tci & htons(VLAN_CFI)) != 0;
case MFP_MPLS:
return eth_type_mpls(flow->dl_type);
+ case MFP_MPLS1:
+ return (eth_type_mpls(flow->dl_type)
+ && !(flow->mpls_lse[0] & htonl(MPLS_BOS_MASK)));
+ case MFP_MPLS2:
+ return (eth_type_mpls(flow->dl_type)
+ && !(flow->mpls_lse[0] & htonl(MPLS_BOS_MASK))
+ && !(flow->mpls_lse[1] & htonl(MPLS_BOS_MASK)));
case MFP_IP_ANY:
return is_ip_any(flow);
@@ -1115,6 +1162,15 @@ mf_mask_field_and_prereqs(const struct mf_field *mf, struct flow *mask)
case MFP_IP_ANY:
mask->dl_type = OVS_BE16_MAX;
break;
+ case MFP_MPLS1:
+ mask->dl_type = OVS_BE16_MAX;
+ mask->mpls_lse[0] = htonl(MPLS_BOS_MASK);
+ break;
+ case MFP_MPLS2:
+ mask->dl_type = OVS_BE16_MAX;
+ mask->mpls_lse[0] = htonl(MPLS_BOS_MASK);
+ mask->mpls_lse[1] = htonl(MPLS_BOS_MASK);
+ break;
case MFP_VLAN_VID:
mask->vlan_tci |= htons(VLAN_CFI);
break;
@@ -1153,6 +1209,9 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
case MFF_ETH_DST:
case MFF_ETH_TYPE:
case MFF_VLAN_TCI:
+ case MFF_MPLS_LSE0:
+ case MFF_MPLS_LSE1:
+ case MFF_MPLS_LSE2:
case MFF_IPV4_SRC:
case MFF_IPV4_DST:
case MFF_IPV6_SRC:
@@ -1312,6 +1371,11 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
case MFF_MPLS_BOS:
value->u8 = mpls_lse_to_bos(flow->mpls_lse[0]);
break;
+
+ case MFF_MPLS_LSE0:
+ case MFF_MPLS_LSE1:
+ case MFF_MPLS_LSE2:
+ value->be32 = flow->mpls_lse[mf->id - MFF_MPLS_LSE0];
break;
case MFF_IPV4_SRC:
@@ -1509,6 +1573,11 @@ mf_set_value(const struct mf_field *mf,
case MFF_MPLS_BOS:
match_set_mpls_bos(match, 0, value->u8);
break;
+
+ case MFF_MPLS_LSE0:
+ case MFF_MPLS_LSE1:
+ case MFF_MPLS_LSE2:
+ match_set_mpls_lse(match, mf->id - MFF_MPLS_LSE0, value->be32);
break;
case MFF_IPV4_SRC:
@@ -1723,6 +1792,11 @@ mf_set_flow_value(const struct mf_field *mf,
case MFF_MPLS_BOS:
flow_set_mpls_bos(flow, 0, value->u8);
break;
+
+ case MFF_MPLS_LSE0:
+ case MFF_MPLS_LSE1:
+ case MFF_MPLS_LSE2:
+ flow->mpls_lse[mf->id - MFF_MPLS_LSE0] = value->be32;
break;
case MFF_IPV4_SRC:
@@ -1934,6 +2008,11 @@ mf_set_wild(const struct mf_field *mf, struct match *match)
case MFF_MPLS_BOS:
match_set_any_mpls_bos(match, 0);
break;
+
+ case MFF_MPLS_LSE0:
+ case MFF_MPLS_LSE1:
+ case MFF_MPLS_LSE2:
+ match_set_any_mpls_lse(match, mf->id - MFF_MPLS_LSE0);
break;
case MFF_IPV4_SRC:
@@ -2074,6 +2153,9 @@ mf_set(const struct mf_field *mf,
case MFF_MPLS_LABEL:
case MFF_MPLS_TC:
case MFF_MPLS_BOS:
+ case MFF_MPLS_LSE0:
+ case MFF_MPLS_LSE1:
+ case MFF_MPLS_LSE2:
case MFF_IP_PROTO:
case MFF_IP_TTL:
case MFF_IP_DSCP:
diff --git a/lib/meta-flow.h b/lib/meta-flow.h
index cf92556..ea81a34 100644
--- a/lib/meta-flow.h
+++ b/lib/meta-flow.h
@@ -85,6 +85,9 @@ enum OVS_PACKED_ENUM mf_field_id {
MFF_MPLS_LABEL, /* be32 */
MFF_MPLS_TC, /* u8 */
MFF_MPLS_BOS, /* u8 */
+ MFF_MPLS_LSE0, /* be32 */
+ MFF_MPLS_LSE1, /* be32 */
+ MFF_MPLS_LSE2, /* be32 */
/* L3. */
MFF_IPV4_SRC, /* be32 */
@@ -193,6 +196,8 @@ enum OVS_PACKED_ENUM mf_prereqs {
/* L2.5 requirements. */
MFP_MPLS,
+ MFP_MPLS1,
+ MFP_MPLS2,
/* L2+L3 requirements. */
MFP_TCP, /* On IPv4 or IPv6. */
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 437e85b..ffa0eb6 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -616,17 +616,39 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match *match,
/* MPLS. */
if (eth_type_mpls(flow->dl_type)) {
- if (match->wc.masks.mpls_lse[0] & htonl(MPLS_TC_MASK)) {
- nxm_put_8(b, OXM_OF_MPLS_TC, mpls_lse_to_tc(flow->mpls_lse[0]));
- }
+ ovs_be32 mask0 = match->wc.masks.mpls_lse[0];
+ if (mask0) {
+ ovs_be32 lse0 = flow->mpls_lse[0];
+ ovs_be32 tc_mask = mask0 & htonl(MPLS_TC_MASK);
+ ovs_be32 bos_mask = mask0 & htonl(MPLS_BOS_MASK);
+ ovs_be32 label_mask = mask0 & htonl(MPLS_LABEL_MASK);
+ ovs_be32 ttl_mask = mask0 & htonl(MPLS_TTL_MASK);
+
+ if ((!tc_mask || tc_mask == htonl(MPLS_TC_MASK)) &&
+ (!bos_mask || bos_mask == htonl(MPLS_BOS_MASK)) &&
+ (!label_mask || label_mask == htonl(MPLS_LABEL_MASK)) &&
+ !ttl_mask)
+ {
+ if (tc_mask) {
+ nxm_put_8(b, OXM_OF_MPLS_TC, mpls_lse_to_tc(lse0));
+ }
+
+ if (bos_mask) {
+ nxm_put_8(b, OXM_OF_MPLS_BOS, mpls_lse_to_bos(lse0));
+ }
- if (match->wc.masks.mpls_lse[0] & htonl(MPLS_BOS_MASK)) {
- nxm_put_8(b, OXM_OF_MPLS_BOS, mpls_lse_to_bos(flow->mpls_lse[0]));
+ if (label_mask) {
+ nxm_put_32(b, OXM_OF_MPLS_LABEL,
+ htonl(mpls_lse_to_label(lse0)));
+ }
+ } else {
+ nxm_put_32m(b, NXM_NX_MPLS_LSE0, lse0, mask0);
+ }
}
- if (match->wc.masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK)) {
- nxm_put_32(b, OXM_OF_MPLS_LABEL,
- htonl(mpls_lse_to_label(flow->mpls_lse[0])));
+ for (i = 1; i < ARRAY_SIZE(flow->mpls_lse); i++) {
+ nxm_put_32m(b, NXM_NX_MPLS_LSE0 + i, flow->mpls_lse[i],
+ match->wc.masks.mpls_lse[i]);
}
}
--
1.7.10.4
More information about the dev
mailing list