From: Jan Scheurich <jan.scheur...@ericsson.com>

Add support for actions push_eth and pop_eth to the netdev datapath and
the supporting libraries. This patch relies on the support for these actions
in the kernel datapath to be present.

Signed-off-by: Lorand Jakab <loja...@cisco.com>
Signed-off-by: Simon Horman <simon.hor...@netronome.com>
Signed-off-by: Jiri Benc <jb...@redhat.com>
Signed-off-by: Yi Yang <yi.y.y...@intel.com>
Signed-off-by: Jean Tourrilhes <j...@labs.hpe.com>
Signed-off-by: Jan Scheurich <jan.scheur...@ericsson.com>
Co-authored-by: Zoltan Balogh <zoltan.bal...@ericsson.com>
---
 datapath/linux/compat/include/linux/openvswitch.h |  6 ++-
 lib/odp-execute.c                                 | 17 +++++-
 lib/odp-util.c                                    | 64 +++++++++++++++++++++--
 lib/odp-util.h                                    |  7 +++
 lib/packets.c                                     | 41 +++++++++++++++
 lib/packets.h                                     |  4 ++
 ofproto/ofproto-dpif-sflow.c                      | 14 ++---
 7 files changed, 138 insertions(+), 15 deletions(-)

diff --git a/datapath/linux/compat/include/linux/openvswitch.h 
b/datapath/linux/compat/include/linux/openvswitch.h
index f2ef0c1..ad979eb 100644
--- a/datapath/linux/compat/include/linux/openvswitch.h
+++ b/datapath/linux/compat/include/linux/openvswitch.h
@@ -747,6 +747,9 @@ enum ovs_ct_attr {
  */
 struct ovs_action_push_eth {
        struct ovs_key_ethernet addresses;
+#ifndef __KERNEL__
+    __be16  eth_type;
+#endif
 };
 
 /**
@@ -823,8 +826,7 @@ enum ovs_nat_attr {
  * entries in the flow key.
  * @OVS_ACTION_ATTR_PUSH_ETH: Push a new outermost Ethernet header onto the
  * packet.
- * @OVS_ACTION_ATTR_POP_ETH: Pop the outermost Ethernet header off the
- * packet.
+ * @OVS_ACTION_ATTR_POP_ETH: Pop the outermost Ethernet header off the packet.
  *
  * Only a single header can be set with a single %OVS_ACTION_ATTR_SET.  Not all
  * fields within a header are modifiable, e.g. the IPv4 protocol and fragment
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index c4563b1..8e090c8 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -732,6 +732,21 @@ odp_execute_actions(void *dp, struct dp_packet_batch 
*batch, bool steal,
         case OVS_ACTION_ATTR_METER:
             /* Not implemented yet. */
             break;
+        case OVS_ACTION_ATTR_PUSH_ETH: {
+            const struct ovs_action_push_eth *eth = nl_attr_get(a);
+
+            DP_PACKET_BATCH_FOR_EACH (packet, batch) {
+                push_eth(packet, &eth->addresses.eth_dst,
+                         &eth->addresses.eth_src, eth->eth_type);
+            }
+            break;
+        }
+
+        case OVS_ACTION_ATTR_POP_ETH:
+            DP_PACKET_BATCH_FOR_EACH (packet, batch) {
+                pop_eth(packet);
+            }
+            break;
 
         case OVS_ACTION_ATTR_OUTPUT:
         case OVS_ACTION_ATTR_TUNNEL_PUSH:
@@ -739,8 +754,6 @@ odp_execute_actions(void *dp, struct dp_packet_batch 
*batch, bool steal,
         case OVS_ACTION_ATTR_USERSPACE:
         case OVS_ACTION_ATTR_RECIRC:
         case OVS_ACTION_ATTR_CT:
-        case OVS_ACTION_ATTR_PUSH_ETH:
-        case OVS_ACTION_ATTR_POP_ETH:
         case OVS_ACTION_ATTR_UNSPEC:
         case __OVS_ACTION_ATTR_MAX:
             OVS_NOT_REACHED();
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 8747778..f137044 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -865,9 +865,11 @@ format_odp_action(struct ds *ds, const struct nlattr *a)
         break;
     case OVS_ACTION_ATTR_PUSH_ETH: {
         const struct ovs_action_push_eth *eth = nl_attr_get(a);
-        ds_put_format(ds, "push_eth(src="ETH_ADDR_FMT",dst="ETH_ADDR_FMT")",
+        ds_put_format(ds, "push_eth(src="ETH_ADDR_FMT",dst="ETH_ADDR_FMT
+                      ",type=0x%04"PRIx16")",
                       ETH_ADDR_ARGS(eth->addresses.eth_src),
-                      ETH_ADDR_ARGS(eth->addresses.eth_dst));
+                      ETH_ADDR_ARGS(eth->addresses.eth_dst),
+                      ntohs(eth->eth_type));
         break;
     }
     case OVS_ACTION_ATTR_POP_ETH:
@@ -1078,14 +1080,41 @@ parse_odp_userspace_action(const char *s, struct ofpbuf 
*actions)
             odp_put_userspace_action(pid, user_data, user_data_size,
                                      tunnel_out_port, include_actions, 
actions);
             res = n + n1;
+            goto out;
         } else if (s[n] == ')') {
             odp_put_userspace_action(pid, user_data, user_data_size,
                                      ODPP_NONE, include_actions, actions);
             res = n + 1;
-        } else {
-            res = -EINVAL;
+            goto out;
+        }
+    }
+
+    {
+        struct ovs_action_push_eth push;
+        int eth_type = 0;
+        int n1 = -1;
+
+        if (ovs_scan(&s[n], "push_eth(src="ETH_ADDR_SCAN_FMT","
+                     "dst="ETH_ADDR_SCAN_FMT",type=%i)%n",
+                     ETH_ADDR_SCAN_ARGS(push.addresses.eth_src),
+                     ETH_ADDR_SCAN_ARGS(push.addresses.eth_dst),
+                     &eth_type, &n1)) {
+
+            nl_msg_put_unspec(actions, OVS_ACTION_ATTR_PUSH_ETH,
+                              &push, sizeof push);
+
+            res = n + n1;
+            goto out;
         }
     }
+
+    if (!strncmp(&s[n], "pop_eth", 7)) {
+        nl_msg_put_flag(actions, OVS_ACTION_ATTR_POP_ETH);
+        res = 7;
+        goto out;
+    }
+
+    res = -EINVAL;
 out:
     ofpbuf_uninit(&buf);
     return res;
@@ -5564,6 +5593,33 @@ odp_put_userspace_action(uint32_t pid,
 }
 
 void
+odp_put_pop_eth_action(struct ofpbuf *odp_actions)
+{
+    nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_ETH);
+}
+
+void
+odp_put_push_eth_action(struct ofpbuf *odp_actions,
+                        const struct eth_addr *eth_src,
+                        const struct eth_addr *eth_dst,
+                        const ovs_be16 eth_type)
+{
+    struct ovs_action_push_eth eth;
+
+    memset(&eth, 0, sizeof eth);
+    if (eth_src) {
+        eth.addresses.eth_src = *eth_src;
+    }
+    if (eth_dst) {
+        eth.addresses.eth_dst = *eth_dst;
+    }
+    eth.eth_type = eth_type;
+
+    nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_PUSH_ETH,
+                      &eth, sizeof eth);
+}
+
+void
 odp_put_tunnel_action(const struct flow_tnl *tunnel,
                       struct ofpbuf *odp_actions)
 {
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 66c194b..cb87c12 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -318,4 +318,11 @@ void odp_put_tunnel_action(const struct flow_tnl *tunnel,
 
 void odp_put_tnl_push_action(struct ofpbuf *odp_actions,
                              struct ovs_action_push_tnl *data);
+
+void odp_put_pop_eth_action(struct ofpbuf *odp_actions);
+void odp_put_push_eth_action(struct ofpbuf *odp_actions,
+                             const struct eth_addr *eth_src,
+                             const struct eth_addr *eth_dst,
+                             const ovs_be16 eth_type);
+
 #endif /* odp-util.h */
diff --git a/lib/packets.c b/lib/packets.c
index 26781b0..3bf5e94 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -226,6 +226,47 @@ eth_pop_vlan(struct dp_packet *packet)
     }
 }
 
+/* Push Ethernet header onto 'packet' assuming it is layer 3 */
+void
+push_eth(struct dp_packet *packet, const struct eth_addr *dst,
+         const struct eth_addr *src, ovs_be16 type)
+{
+    struct eth_header *eh;
+
+    ovs_assert(packet->packet_type != htonl(PT_ETH));
+    eh = dp_packet_resize_l2(packet, ETH_HEADER_LEN);
+    eh->eth_dst = *dst;
+    eh->eth_src = *src;
+    eh->eth_type = type;
+    packet->packet_type = htonl(PT_ETH);
+}
+
+/* Removes Ethernet header, including VLAN header, from 'packet'.
+ *
+ * Previous to calling this function, 'ofpbuf_l3(packet)' must not be NULL */
+void
+pop_eth(struct dp_packet *packet)
+{
+    char *l2_5 = dp_packet_l2_5(packet);
+    char *l3 = dp_packet_l3(packet);
+    ovs_be16 ethertype;
+    int increment;
+
+    ovs_assert(packet->packet_type == htonl(PT_ETH));
+    ovs_assert(l3 != NULL);
+
+    if (l2_5) {
+        increment = packet->l2_5_ofs;
+        ethertype = *(ALIGNED_CAST(ovs_be16 *, (l2_5 - 2)));
+    } else {
+        increment = packet->l3_ofs;
+        ethertype = *(ALIGNED_CAST(ovs_be16 *, (l3 - 2)));
+    }
+
+    dp_packet_resize_l2(packet, -increment);
+    packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE, htons(ethertype));
+}
+
 /* Set ethertype of the packet. */
 static void
 set_ethertype(struct dp_packet *packet, ovs_be16 eth_type)
diff --git a/lib/packets.h b/lib/packets.h
index 092e7c5..3a8ac74 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -371,6 +371,10 @@ struct eth_header {
 });
 BUILD_ASSERT_DECL(ETH_HEADER_LEN == sizeof(struct eth_header));
 
+void push_eth(struct dp_packet *packet, const struct eth_addr *dst,
+              const struct eth_addr *src, ovs_be16 type);
+void pop_eth(struct dp_packet *packet);
+
 #define LLC_DSAP_SNAP 0xaa
 #define LLC_SSAP_SNAP 0xaa
 #define LLC_CNTL_SNAP 3
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index 59fafa1..43483d7 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -1188,13 +1188,13 @@ dpif_sflow_read_actions(const struct flow *flow,
            dpif_sflow_pop_mpls_lse(sflow_actions);
            break;
        }
-        case OVS_ACTION_ATTR_PUSH_ETH:
-        case OVS_ACTION_ATTR_POP_ETH:
-            /* TODO: SFlow does not currently define a MAC-in-MAC
-             * encapsulation structure.  We could use an extension
-             * structure to report this.
-             */
-            break;
+       case OVS_ACTION_ATTR_PUSH_ETH:
+       case OVS_ACTION_ATTR_POP_ETH:
+           /* TODO: SFlow does not currently define a MAC-in-MAC
+            * encapsulation structure.  We could use an extension
+            * structure to report this.
+            */
+           break;
        case OVS_ACTION_ATTR_SAMPLE:
        case OVS_ACTION_ATTR_CLONE:
        case OVS_ACTION_ATTR_UNSPEC:
-- 
2.7.4
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to