netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
To: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: ryazanov.s.a-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	jasowang-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
	john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
	Neil.Jerram-QnUH15yq9NYqDJ6do+/SaQ@public.gmane.org,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
	andy-QlMahl40kYEqcZcGjlUOXw@public.gmane.org,
	dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org,
	nbd-p3rKhJxN3npAfugRpC6u6w@public.gmane.org,
	f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org,
	ben-/+tVBieCtBitmTQ+vhA3Yw@public.gmane.org,
	buytenh-OLH4Qvv75CYX/NnBR394Jw@public.gmane.org,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR@public.gmane.org,
	jhs-jkUAjuhPggJWk0Htik3J/w@public.gmane.org,
	linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org,
	aviadr-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org,
	nicolas.dichtel-pdR9zngts4EAvxtiuMwx3w@public.gmane.org,
	vyasevic-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
	nhorman-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR@public.gmane.org,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ@public.gmane.org,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
	ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org
Subject: [patch net-next RFC v3 10/10] openvswitch: add support for datapath hardware offload
Date: Thu, 17 Apr 2014 14:15:38 +0200	[thread overview]
Message-ID: <1397736938-11838-1-git-send-email-jiri@resnulli.us> (raw)
In-Reply-To: <1397736876-11771-1-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>

Benefit from the possibility to work with flows in switch devices and
use the swdev api to offload flow datapath.

Signed-off-by: Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
---
 include/linux/sw_flow.h      |  16 +++-
 net/openvswitch/Makefile     |   3 +-
 net/openvswitch/datapath.c   |  16 +++-
 net/openvswitch/hw_offload.c | 170 +++++++++++++++++++++++++++++++++++++++++++
 net/openvswitch/hw_offload.h |  31 ++++++++
 5 files changed, 231 insertions(+), 5 deletions(-)
 create mode 100644 net/openvswitch/hw_offload.c
 create mode 100644 net/openvswitch/hw_offload.h

diff --git a/include/linux/sw_flow.h b/include/linux/sw_flow.h
index 3bbd5aa..12a24f9 100644
--- a/include/linux/sw_flow.h
+++ b/include/linux/sw_flow.h
@@ -102,7 +102,21 @@ struct sw_flow {
 	struct sw_flow_mask *mask;
 };
 
+enum sw_flow_action_type {
+	SW_FLOW_ACTION_TYPE_OUTPUT,
+	SW_FLOW_ACTION_TYPE_VLAN_PUSH,
+	SW_FLOW_ACTION_TYPE_VLAN_POP,
+};
+
 struct sw_flow_action {
-}
+	enum sw_flow_action_type type;
+	union {
+		struct net_device *output_dev;
+		struct {
+			__be16 vlan_proto;
+			u16 vlan_tci;
+		} vlan;
+	};
+};
 
 #endif /* _LINUX_SW_FLOW_H_ */
diff --git a/net/openvswitch/Makefile b/net/openvswitch/Makefile
index 3591cb5..5152437 100644
--- a/net/openvswitch/Makefile
+++ b/net/openvswitch/Makefile
@@ -13,7 +13,8 @@ openvswitch-y := \
 	flow_table.o \
 	vport.o \
 	vport-internal_dev.o \
-	vport-netdev.o
+	vport-netdev.o \
+	hw_offload.o
 
 ifneq ($(CONFIG_OPENVSWITCH_VXLAN),)
 openvswitch-y += vport-vxlan.o
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 10ffb0a..f1e0792 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -59,6 +59,7 @@
 #include "flow_netlink.h"
 #include "vport-internal_dev.h"
 #include "vport-netdev.h"
+#include "hw_offload.h"
 
 int ovs_net_id __read_mostly;
 
@@ -840,13 +841,15 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 		flow->flow.key = masked_key;
 		flow->flow.unmasked_key = key;
 		rcu_assign_pointer(flow->sf_acts, acts);
+		acts = NULL;
 
 		/* Put flow in bucket. */
 		error = ovs_flow_tbl_insert(&dp->table, flow, &mask);
-		if (error) {
-			acts = NULL;
+		if (error)
 			goto err_flow_free;
-		}
+		error = ovs_hw_flow_insert(dp, flow, flow->sf_acts);
+		if (error)
+			goto err_flow_tbl_remove;
 
 		reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
 	} else {
@@ -868,6 +871,10 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 		if (!ovs_flow_cmp_unmasked_key(flow, &match))
 			goto err_unlock_ovs;
 
+		error = ovs_hw_flow_actions_update(dp, flow, acts);
+		if (error)
+			goto err_unlock_ovs;
+
 		/* Update actions. */
 		old_acts = ovsl_dereference(flow->sf_acts);
 		rcu_assign_pointer(flow->sf_acts, acts);
@@ -888,6 +895,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 			     0, PTR_ERR(reply));
 	return 0;
 
+err_flow_tbl_remove:
+	ovs_flow_tbl_remove(&dp->table, flow);
 err_flow_free:
 	ovs_flow_free(flow, false);
 err_unlock_ovs:
@@ -985,6 +994,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
 		goto unlock;
 	}
 
+	ovs_hw_flow_remove(dp, flow);
 	ovs_flow_tbl_remove(&dp->table, flow);
 
 	err = ovs_flow_cmd_fill_info(flow, dp, reply, info->snd_portid,
diff --git a/net/openvswitch/hw_offload.c b/net/openvswitch/hw_offload.c
new file mode 100644
index 0000000..c4c64d0
--- /dev/null
+++ b/net/openvswitch/hw_offload.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2014 Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/rcupdate.h>
+#include <linux/netdevice.h>
+#include <linux/sw_flow.h>
+#include <linux/switchdev.h>
+
+#include "datapath.h"
+#include "vport-netdev.h"
+
+static struct net_device *__dp_master(struct datapath *dp)
+{
+	struct vport *local;
+
+	local = ovs_vport_ovsl_rcu(dp, OVSP_LOCAL);
+	BUG_ON(!local);
+	return local->ops->get_netdev(local);
+}
+
+static int sw_flow_action_create(struct datapath *dp,
+				 struct sw_flow_action **p_action,
+				 size_t *p_action_count,
+				 struct sw_flow_actions *acts)
+{
+	const struct nlattr *attr = acts->actions;
+	int len = acts->actions_len;
+	const struct nlattr *a;
+	int rem;
+	struct sw_flow_action *action, *cur;
+	size_t action_count = 0;
+	int err;
+
+	for (a = attr, rem = len; rem > 0; a = nla_next(a, &rem))
+		action_count++;
+
+	action = kzalloc(sizeof(*action) * action_count, GFP_KERNEL);
+	if (!action)
+		return -ENOMEM;
+
+	cur = action;
+	for (a = attr, rem = len; rem > 0; a = nla_next(a, &rem)) {
+		switch (nla_type(a)) {
+		case OVS_ACTION_ATTR_OUTPUT:
+			{
+				struct vport *vport;
+
+				vport = ovs_vport_ovsl_rcu(dp, nla_get_u32(a));
+				if (vport->ops->type != OVS_VPORT_TYPE_NETDEV) {
+					err = -EOPNOTSUPP;
+					goto errout;
+				}
+				cur->type = SW_FLOW_ACTION_TYPE_OUTPUT;
+				cur->output_dev = vport->ops->get_netdev(vport);
+			}
+			break;
+
+		case OVS_ACTION_ATTR_PUSH_VLAN:
+			{
+				const struct ovs_action_push_vlan *vlan;
+
+				vlan = nla_data(a);
+				cur->type = SW_FLOW_ACTION_TYPE_VLAN_PUSH;
+				cur->vlan.vlan_proto = vlan->vlan_tpid;
+				cur->vlan.vlan_tci = vlan->vlan_tci;
+			}
+			break;
+
+		case OVS_ACTION_ATTR_POP_VLAN:
+			cur->type = SW_FLOW_ACTION_TYPE_VLAN_POP;
+			break;
+
+		default:
+			err = -EOPNOTSUPP;
+			goto errout;
+		}
+		action++;
+	}
+	*p_action = action;
+	*p_action_count = action_count;
+	return 0;
+
+errout:
+	kfree(action);
+	return err;
+}
+
+int ovs_hw_flow_insert(struct datapath *dp, struct ovs_flow *flow,
+		       struct sw_flow_actions *acts)
+{
+	struct list_head *iter;
+	struct net_device *dev;
+	struct sw_flow_action *action;
+	size_t action_count;
+	int err;
+
+	err = sw_flow_action_create(dp, &action, &action_count, acts);
+	if (err)
+		return err;
+
+	rcu_read_lock();
+	netdev_for_each_all_lower_dev_rcu(__dp_master(dp), dev, iter) {
+		err = swdev_flow_insert(dev, &flow->flow);
+		if (err && err != -EOPNOTSUPP)
+			break;
+		err = swdev_flow_action_set(dev, &flow->flow,
+					    action, action_count);
+		if (err && err != -EOPNOTSUPP)
+			break;
+	}
+	rcu_read_unlock();
+
+	kfree(action);
+
+	return err;
+}
+
+void ovs_hw_flow_remove(struct datapath *dp, struct ovs_flow *flow)
+{
+	struct list_head *iter;
+	struct net_device *dev;
+
+	rcu_read_lock();
+	netdev_for_each_all_lower_dev_rcu(__dp_master(dp), dev, iter)
+		swdev_flow_remove(dev, &flow->flow);
+	rcu_read_unlock();
+}
+
+int ovs_hw_flow_actions_update(struct datapath *dp, struct ovs_flow *flow,
+			       struct sw_flow_actions *acts)
+{
+	struct list_head *iter;
+	struct net_device *dev;
+	struct sw_flow_action *action;
+	size_t action_count;
+	int err;
+
+	err = sw_flow_action_create(dp, &action, &action_count, acts);
+	if (err)
+		return err;
+
+	rcu_read_lock();
+	netdev_for_each_all_lower_dev_rcu(__dp_master(dp), dev, iter) {
+		err = swdev_flow_action_set(dev, &flow->flow,
+					    action, action_count);
+		if (err && err != -EOPNOTSUPP)
+			break;
+	}
+	rcu_read_unlock();
+
+	kfree(action);
+
+	return err;
+}
diff --git a/net/openvswitch/hw_offload.h b/net/openvswitch/hw_offload.h
new file mode 100644
index 0000000..7ecb60f
--- /dev/null
+++ b/net/openvswitch/hw_offload.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014 Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#ifndef HW_OFFLOAD_H
+#define HW_OFFLOAD_H 1
+
+#include "datapath.h"
+#include "flow.h"
+
+int ovs_hw_flow_insert(struct datapath *dp, struct ovs_flow *flow,
+		       struct sw_flow_actions *acts);
+void ovs_hw_flow_remove(struct datapath *dp, struct ovs_flow *flow);
+int ovs_hw_flow_actions_update(struct datapath *dp, struct ovs_flow *flow,
+			       struct sw_flow_actions *acts);
+
+#endif
-- 
1.9.0

  parent reply	other threads:[~2014-04-17 12:15 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-17 12:14 [patch net-next RFC v3 00/10] introduce infrastructure for support of switch chip datapath Jiri Pirko
2014-04-17 12:14 ` [patch net-next RFC v3 02/10] net: rename netdev_phys_port_id to more generic name Jiri Pirko
     [not found]   ` <1397736876-11771-3-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
2014-04-17 15:01     ` Stephen Hemminger
     [not found]       ` <20140417080110.73485409-We1ePj4FEcvRI77zikRAJc56i+j3xesD0e7PPNI6Mm0@public.gmane.org>
2014-04-17 15:05         ` Jiri Pirko
2014-04-17 12:14 ` [patch net-next RFC v3 03/10] net: introduce generic switch devices support Jiri Pirko
2014-04-17 12:14 ` [patch net-next RFC v3 04/10] rtnl: expose physical switch id for particular device Jiri Pirko
2014-04-17 12:40   ` Yegor Yefremov
2014-04-17 12:14 ` [patch net-next RFC v3 05/10] switchdev: introduce basic support for flows Jiri Pirko
2014-04-17 12:14 ` [patch net-next RFC v3 07/10] dsa: implement ndo_swdev_get_id Jiri Pirko
2014-04-17 12:14 ` [patch net-next RFC v3 09/10] openvswitch: introduce vport_op get_netdev Jiri Pirko
     [not found] ` <1397736876-11771-1-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
2014-04-17 12:14   ` [patch net-next RFC v3 01/10] openvswitch: split flow structures into ovs specific and generic ones Jiri Pirko
2014-04-17 12:14   ` [patch net-next RFC v3 06/10] net: introduce dummy switch Jiri Pirko
2014-04-17 12:14   ` [patch net-next RFC v3 08/10] net: add netdev_for_each_all_lower_dev_rcu helper Jiri Pirko
2014-04-17 12:15   ` Jiri Pirko [this message]
     [not found]     ` <1397736938-11838-1-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
2014-04-24 14:54       ` [patch net-next RFC v3 10/10] openvswitch: add support for datapath hardware offload John Fastabend
     [not found]         ` <5359259B.3020402-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-04-24 15:46           ` Jiri Pirko
     [not found]             ` <20140424154614.GB2864-RDzucLLXGGI88b5SBfVpbw@public.gmane.org>
2014-04-24 15:58               ` John Fastabend
2014-04-17 12:17   ` [patch net-next RFC v3 0/5] iproute2: support switch chip infrastructure Jiri Pirko
     [not found]     ` <1397737053-11892-1-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
2014-04-17 12:17       ` [patch iproute2 RFC v3 1/5] iproute2: arpd: use ll_addr_a2n and ll_addr_n2a Jiri Pirko
2014-04-17 12:17       ` [patch iproute2 RFC v3 2/5] iproute2: utils: change hexstring_n2a and hexstring_a2n to do not work with ":" Jiri Pirko
2014-04-17 12:17       ` [patch iproute2 RFC v3 3/5] iproute2: ipa: show switch id Jiri Pirko
2014-04-17 12:17       ` [patch iproute2 RFC v3 4/5] iproute2: add support for dummyswport Jiri Pirko
2014-04-17 13:19         ` Nicolas Dichtel
2014-04-17 12:17       ` [patch iproute2 RFC v3 5/5] iproute2: ipa: show port id Jiri Pirko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1397736938-11838-1-git-send-email-jiri@resnulli.us \
    --to=jiri-rhqaubhg3fbzbrfiqnyvsa@public.gmane.org \
    --cc=Neil.Jerram-QnUH15yq9NYqDJ6do+/SaQ@public.gmane.org \
    --cc=andy-QlMahl40kYEqcZcGjlUOXw@public.gmane.org \
    --cc=aviadr-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org \
    --cc=ben-/+tVBieCtBitmTQ+vhA3Yw@public.gmane.org \
    --cc=buytenh-OLH4Qvv75CYX/NnBR394Jw@public.gmane.org \
    --cc=davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org \
    --cc=dborkman-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
    --cc=dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org \
    --cc=ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org \
    --cc=edumazet-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
    --cc=f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=jasowang-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
    --cc=jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
    --cc=jhs-jkUAjuhPggJWk0Htik3J/w@public.gmane.org \
    --cc=john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
    --cc=linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org \
    --cc=nbd-p3rKhJxN3npAfugRpC6u6w@public.gmane.org \
    --cc=netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=nhorman-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org \
    --cc=nicolas.dichtel-pdR9zngts4EAvxtiuMwx3w@public.gmane.org \
    --cc=ogerlitz-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org \
    --cc=roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR@public.gmane.org \
    --cc=ryazanov.s.a-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR@public.gmane.org \
    --cc=stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ@public.gmane.org \
    --cc=vyasevic-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).