This is to match the kernel implementation in the
patch "datapath: Add basic MPLS support to kernel"
by Leo Alterman.

Cc: Leo Alterman <lalter...@nicira.com>
Signed-off-by: Simon Horman <ho...@verge.net.au>

---

v2.2
* No change

v2.1
* Initial post
---
 lib/dpif-netdev.c |   13 +++++++++++++
 lib/odp-util.c    |   43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index c9e3210..6deb9ff 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -1212,6 +1212,7 @@ execute_set_action(struct ofpbuf *packet, const struct 
nlattr *a)
      case OVS_KEY_ATTR_ICMPV6:
      case OVS_KEY_ATTR_ARP:
      case OVS_KEY_ATTR_ND:
+     case OVS_KEY_ATTR_MPLS:
      case __OVS_KEY_ATTR_MAX:
      default:
         NOT_REACHED();
@@ -1249,6 +1250,18 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
             eth_pop_vlan(packet);
             break;
 
+        case OVS_ACTION_ATTR_PUSH_MPLS:
+            push_mpls(packet, nl_attr_get_be16(a));
+            break;
+
+        case OVS_ACTION_ATTR_POP_MPLS:
+             pop_mpls(packet, nl_attr_get_be16(a));
+             break;
+
+        case OVS_ACTION_ATTR_SET_MPLS:
+             set_mpls_lse(packet, nl_attr_get_be32(a));
+             break;
+
         case OVS_ACTION_ATTR_SET:
             execute_set_action(packet, nl_attr_get(a));
             break;
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 257d7a7..13b3248 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -73,6 +73,9 @@ odp_action_len(uint16_t type)
     case OVS_ACTION_ATTR_USERSPACE: return -2;
     case OVS_ACTION_ATTR_PUSH_VLAN: return sizeof(struct ovs_action_push_vlan);
     case OVS_ACTION_ATTR_POP_VLAN: return 0;
+    case OVS_ACTION_ATTR_PUSH_MPLS: return sizeof(struct ovs_action_push_mpls);
+    case OVS_ACTION_ATTR_POP_MPLS: return sizeof(ovs_be16);
+    case OVS_ACTION_ATTR_SET_MPLS: return sizeof(ovs_be32);
     case OVS_ACTION_ATTR_SET: return -2;
     case OVS_ACTION_ATTR_SAMPLE: return -2;
 
@@ -106,6 +109,7 @@ ovs_key_attr_to_string(enum ovs_key_attr attr)
     case OVS_KEY_ATTR_ARP: return "arp";
     case OVS_KEY_ATTR_ND: return "nd";
     case OVS_KEY_ATTR_TUN_ID: return "tun_id";
+    case OVS_KEY_ATTR_MPLS: return "mpls";
 
     case __OVS_KEY_ATTR_MAX:
     default:
@@ -273,6 +277,17 @@ format_vlan_tci(struct ds *ds, ovs_be16 vlan_tci)
 }
 
 static void
+format_mpls_lse(struct ds *ds, ovs_be32 mpls_lse)
+{
+    ds_put_format(ds, "label=%"PRIu32",tc=%d,ttl=%d,bos=%d",
+                  mpls_lse_to_label(mpls_lse),
+                  mpls_lse_to_tc(mpls_lse),
+                  mpls_lse_to_ttl(mpls_lse),
+                  mpls_lse_to_stack(mpls_lse));
+}
+
+
+static void
 format_odp_action(struct ds *ds, const struct nlattr *a)
 {
     int expected_len;
@@ -311,6 +326,25 @@ format_odp_action(struct ds *ds, const struct nlattr *a)
     case OVS_ACTION_ATTR_POP_VLAN:
         ds_put_cstr(ds, "pop_vlan");
         break;
+    case OVS_ACTION_ATTR_PUSH_MPLS: {
+        const struct ovs_action_push_mpls *mpls = nl_attr_get(a);
+        ds_put_cstr(ds, "push_mpls(");
+        format_mpls_lse(ds, mpls->mpls_label);
+        ds_put_format(ds, "eth_type=0x%"PRIx16")", 
ntohs(mpls->mpls_ethertype));
+        break;
+    }
+    case OVS_ACTION_ATTR_POP_MPLS: {
+        ovs_be16 ethertype = nl_attr_get_be16(a);
+        ds_put_format(ds, "pop_mpls(eth_type=0x%"PRIx16")", ntohs(ethertype));
+        break;
+                                   }
+    case OVS_ACTION_ATTR_SET_MPLS: {
+        ovs_be32 label = nl_attr_get_be32(a);
+        ds_put_cstr(ds, "set_mpls(");
+        format_mpls_lse(ds, label);
+        ds_put_char(ds, ')');
+        break;
+    }
     case OVS_ACTION_ATTR_SAMPLE:
         format_odp_sample_action(ds, a);
         break;
@@ -606,6 +640,7 @@ odp_flow_key_attr_len(uint16_t type)
     case OVS_KEY_ATTR_ETHERNET: return sizeof(struct ovs_key_ethernet);
     case OVS_KEY_ATTR_VLAN: return sizeof(ovs_be16);
     case OVS_KEY_ATTR_ETHERTYPE: return 2;
+    case OVS_KEY_ATTR_MPLS: return sizeof(struct ovs_key_mpls);
     case OVS_KEY_ATTR_IPV4: return sizeof(struct ovs_key_ipv4);
     case OVS_KEY_ATTR_IPV6: return sizeof(struct ovs_key_ipv6);
     case OVS_KEY_ATTR_TCP: return sizeof(struct ovs_key_tcp);
@@ -715,6 +750,14 @@ format_odp_key_attr(const struct nlattr *a, struct ds *ds)
         ds_put_char(ds, ')');
         break;
 
+    case OVS_KEY_ATTR_MPLS: {
+        const struct ovs_key_mpls *mpls_key = nl_attr_get(a);
+        ds_put_char(ds, '(');
+        format_mpls_lse(ds, mpls_key->mpls_top_label);
+        ds_put_char(ds, ')');
+        break;
+    }
+
     case OVS_KEY_ATTR_ETHERTYPE:
         ds_put_format(ds, "(0x%04"PRIx16")",
                       ntohs(nl_attr_get_be16(a)));
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to