All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
@ 2014-03-26 16:31 Jiri Pirko
  2014-03-26 16:31 ` [patch net-next RFC v2 1/6] net: make packet_type->ak_packet_priv generic Jiri Pirko
                   ` (5 more replies)
  0 siblings, 6 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-26 16:31 UTC (permalink / raw
  To: netdev
  Cc: davem, nhorman, andy, tgraf, dborkman, ogerlitz, jesse, pshelar,
	azhou, ben, stephen, jeffrey.t.kirsher, vyasevic, xiyou.wangcong,
	john.r.fastabend, edumazet, jhs, sfeldma, f.fainelli, roopa,
	linville, dev

This is second version of RFC. Here are the main differences from the first one:
-There is no special swdev of swport structure. The switch and its ports are
 now represented only by net_device structures. There are couple of switch-specific
 ndos added (inserting and removing flows).

-Regarding the flows, driver marks skb with "missing flow" flag now. That would
 give indication to a user (OVS datapath of af_packet userspace application).
 On the opposite direction, skb can be xmitted by a port.

-dummyswitch module has now rtnetlink iface for easy creation of dummy switches
 and ports.

The basic idea is to introduce a generic infractructure to support various
switch chips in kernel. Also the idea is to benefit of currently existing
Open vSwitch userspace infrastructure.


The first two patches are just minor skb flag and packet_type modifications.


The third patch does a split of structures which are not specific to OVS
into more generic ones that can be reused.


The fourth patch introduces the "switchdev" API itself. It should serve as
a glue between chip drivers on the one side and the user on the other.
That user might be OVS datapath but in future it might be just userspace
application interacting via af_packet and Netlink iface.

The infrastructure is designed to be similar to for example linux bridge.
There is one netdevice representing a switch chip and one netdevice per every
port. These are bound together in classic slave-master way. The reason
to reuse the netdevices for port representation is that userspace can use
standard tools to get information about the ports, statistics, tcpdump, etc.

Note that the netdevices are just representations of the ports in the switch.
Therefore **no actual data** goes though, only missed flow skbs and, if drivers
supports it, when ETH_P_ALL packet_type is hooked on (tcpdump).


The fifth patch introduces a support for switchdev vports into OVS datapath.
After that, userspace would be able to create a switchdev DP for a switch chip,
to add switchdev ports to it and to use it in the same way as it would be
OVS SW datapath.


The sixth patch adds a dummy switch module. It is just an example of
switchdev driver implementation.


Jiri Pirko (6):
  net: make packet_type->ak_packet_priv generic
  skbuff: add "missed_flow" flag
  openvswitch: split flow structures into ovs specific and generic ones
  net: introduce switchdev API
  openvswitch: Introduce support for switchdev based datapath
  net: introduce dummy switch

 drivers/net/Kconfig                        |   7 +
 drivers/net/Makefile                       |   1 +
 drivers/net/dummyswitch.c                  | 235 +++++++++++++++++++++++++++++
 include/linux/filter.h                     |   1 +
 include/linux/netdevice.h                  |  26 +++-
 include/linux/skbuff.h                     |  13 ++
 include/linux/sw_flow.h                    | 105 +++++++++++++
 include/linux/switchdev.h                  |  30 ++++
 include/uapi/linux/if_link.h               |   9 ++
 include/uapi/linux/openvswitch.h           |   4 +
 net/Kconfig                                |  10 ++
 net/core/Makefile                          |   1 +
 net/core/dev.c                             |   4 +-
 net/core/filter.c                          |   3 +
 net/core/switchdev.c                       | 172 +++++++++++++++++++++
 net/openvswitch/Makefile                   |   4 +
 net/openvswitch/datapath.c                 |  90 +++++++----
 net/openvswitch/datapath.h                 |  12 +-
 net/openvswitch/dp_notify.c                |   3 +-
 net/openvswitch/flow.c                     |  14 +-
 net/openvswitch/flow.h                     | 123 +++------------
 net/openvswitch/flow_netlink.c             |  24 +--
 net/openvswitch/flow_netlink.h             |   4 +-
 net/openvswitch/flow_table.c               | 100 ++++++------
 net/openvswitch/flow_table.h               |  18 +--
 net/openvswitch/vport-gre.c                |   4 +-
 net/openvswitch/vport-internal_switchdev.c | 179 ++++++++++++++++++++++
 net/openvswitch/vport-internal_switchdev.h |  28 ++++
 net/openvswitch/vport-netdev.c             |   4 +-
 net/openvswitch/vport-switchportdev.c      | 205 +++++++++++++++++++++++++
 net/openvswitch/vport-switchportdev.h      |  24 +++
 net/openvswitch/vport-vxlan.c              |   2 +-
 net/openvswitch/vport.c                    |   6 +-
 net/openvswitch/vport.h                    |   4 +-
 net/packet/af_packet.c                     |  22 ++-
 35 files changed, 1269 insertions(+), 222 deletions(-)
 create mode 100644 drivers/net/dummyswitch.c
 create mode 100644 include/linux/sw_flow.h
 create mode 100644 include/linux/switchdev.h
 create mode 100644 net/core/switchdev.c
 create mode 100644 net/openvswitch/vport-internal_switchdev.c
 create mode 100644 net/openvswitch/vport-internal_switchdev.h
 create mode 100644 net/openvswitch/vport-switchportdev.c
 create mode 100644 net/openvswitch/vport-switchportdev.h

-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [patch net-next RFC v2 1/6] net: make packet_type->ak_packet_priv generic
  2014-03-26 16:31 [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath Jiri Pirko
@ 2014-03-26 16:31 ` Jiri Pirko
  2014-03-26 16:31 ` [patch net-next RFC v2 2/6] skbuff: add "missed_flow" flag Jiri Pirko
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-26 16:31 UTC (permalink / raw
  To: netdev
  Cc: davem, nhorman, andy, tgraf, dborkman, ogerlitz, jesse, pshelar,
	azhou, ben, stephen, jeffrey.t.kirsher, vyasevic, xiyou.wangcong,
	john.r.fastabend, edumazet, jhs, sfeldma, f.fainelli, roopa,
	linville, dev

The priv is used now by af_packet. Rename it to make it useable for
others as well. Also, introduce packet_id_match to move the sk matching
from skb_loop_sk to af_packet code where it belongs.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 include/linux/netdevice.h |  2 +-
 net/core/dev.c            |  4 +---
 net/packet/af_packet.c    | 22 +++++++++++++++-------
 3 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 4b6d12c..6b70e6f 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1777,7 +1777,7 @@ struct packet_type {
 					 struct net_device *);
 	bool			(*id_match)(struct packet_type *ptype,
 					    struct sock *sk);
-	void			*af_packet_priv;
+	void			*priv;
 	struct list_head	list;
 };
 
diff --git a/net/core/dev.c b/net/core/dev.c
index 55f8e64..61ce72d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1719,13 +1719,11 @@ static inline int deliver_skb(struct sk_buff *skb,
 
 static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb)
 {
-	if (!ptype->af_packet_priv || !skb->sk)
+	if (!ptype->priv || !skb->sk)
 		return false;
 
 	if (ptype->id_match)
 		return ptype->id_match(ptype, skb->sk);
-	else if ((struct sock *)ptype->af_packet_priv == skb->sk)
-		return true;
 
 	return false;
 }
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 2923044..a36ac08 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1343,7 +1343,7 @@ static bool fanout_has_flag(struct packet_fanout *f, u16 flag)
 static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
 			     struct packet_type *pt, struct net_device *orig_dev)
 {
-	struct packet_fanout *f = pt->af_packet_priv;
+	struct packet_fanout *f = pt->priv;
 	unsigned int num = f->num_members;
 	struct packet_sock *po;
 	unsigned int idx;
@@ -1425,7 +1425,7 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po)
 
 static bool match_fanout_group(struct packet_type *ptype, struct sock *sk)
 {
-	if (ptype->af_packet_priv == (void *)((struct packet_sock *)sk)->fanout)
+	if (ptype->priv == (void *)((struct packet_sock *)sk)->fanout)
 		return true;
 
 	return false;
@@ -1487,7 +1487,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
 		match->prot_hook.type = po->prot_hook.type;
 		match->prot_hook.dev = po->prot_hook.dev;
 		match->prot_hook.func = packet_rcv_fanout;
-		match->prot_hook.af_packet_priv = match;
+		match->prot_hook.priv = match;
 		match->prot_hook.id_match = match_fanout_group;
 		dev_add_pack(&match->prot_hook);
 		list_add(&match->list, &fanout_list);
@@ -1545,7 +1545,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,
 	 *	field for just this event.
 	 */
 
-	sk = pt->af_packet_priv;
+	sk = pt->priv;
 
 	/*
 	 *	Yank back the headers [hope the device set this
@@ -1768,7 +1768,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (skb->pkt_type == PACKET_LOOPBACK)
 		goto drop;
 
-	sk = pt->af_packet_priv;
+	sk = pt->priv;
 	po = pkt_sk(sk);
 
 	if (!net_eq(dev_net(dev), sock_net(sk)))
@@ -1893,7 +1893,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (skb->pkt_type == PACKET_LOOPBACK)
 		goto drop;
 
-	sk = pt->af_packet_priv;
+	sk = pt->priv;
 	po = pkt_sk(sk);
 
 	if (!net_eq(dev_net(dev), sock_net(sk)))
@@ -2768,6 +2768,13 @@ static struct proto packet_proto = {
 	.obj_size = sizeof(struct packet_sock),
 };
 
+static bool packet_id_match(struct packet_type *ptype, struct sock *sk)
+{
+	if ((struct sock *) ptype->priv == sk)
+		return true;
+	return false;
+}
+
 /*
  *	Create a packet of type SOCK_PACKET.
  */
@@ -2824,7 +2831,8 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
 	if (sock->type == SOCK_PACKET)
 		po->prot_hook.func = packet_rcv_spkt;
 
-	po->prot_hook.af_packet_priv = sk;
+	po->prot_hook.id_match = packet_id_match,
+	po->prot_hook.priv = sk;
 
 	if (proto) {
 		po->prot_hook.type = proto;
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [patch net-next RFC v2 2/6] skbuff: add "missed_flow" flag
  2014-03-26 16:31 [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath Jiri Pirko
  2014-03-26 16:31 ` [patch net-next RFC v2 1/6] net: make packet_type->ak_packet_priv generic Jiri Pirko
@ 2014-03-26 16:31 ` Jiri Pirko
       [not found]   ` <1395851472-10524-3-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
  2014-03-26 16:31 ` [patch net-next RFC v2 3/6] openvswitch: split flow structures into ovs specific and generic ones Jiri Pirko
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 31+ messages in thread
From: Jiri Pirko @ 2014-03-26 16:31 UTC (permalink / raw
  To: netdev
  Cc: davem, nhorman, andy, tgraf, dborkman, ogerlitz, jesse, pshelar,
	azhou, ben, stephen, jeffrey.t.kirsher, vyasevic, xiyou.wangcong,
	john.r.fastabend, edumazet, jhs, sfeldma, f.fainelli, roopa,
	linville, dev

This flag sets incoming switch device in order to let know that the flow
which the skb is part of is missed. Listener may react to it
appropriately,

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 include/linux/filter.h |  1 +
 include/linux/skbuff.h | 13 +++++++++++++
 net/core/filter.c      |  3 +++
 3 files changed, 17 insertions(+)

diff --git a/include/linux/filter.h b/include/linux/filter.h
index e568c8e..38c7c04 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -154,6 +154,7 @@ enum {
 	BPF_S_ANC_VLAN_TAG,
 	BPF_S_ANC_VLAN_TAG_PRESENT,
 	BPF_S_ANC_PAY_OFFSET,
+	BPF_S_ANC_MISSED_FLOW,
 };
 
 #endif /* __LINUX_FILTER_H__ */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 03db95a..0100c2f 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -567,6 +567,7 @@ struct sk_buff {
 	 * headers if needed
 	 */
 	__u8			encapsulation:1;
+	__u8			missed_flow:1;
 	/* 6/8 bit hole (depending on ndisc_nodetype presence) */
 	kmemcheck_bitfield_end(flags2);
 
@@ -2993,5 +2994,17 @@ static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
 			       skb_network_header(skb);
 	return hdr_len + skb_gso_transport_seglen(skb);
 }
+
+/**
+ * skb_mark_missed_flow - marks skb as a part of missed flow
+ * @skb: buffer
+ *
+ * Marks skb as a part of missed flow.
+ */
+static inline void skb_mark_missed_flow(struct sk_buff *skb)
+{
+	skb->missed_flow = 1;
+}
+
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SKBUFF_H */
diff --git a/net/core/filter.c b/net/core/filter.c
index ad30d62..048f11a 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -350,6 +350,9 @@ load_b:
 		case BPF_S_ANC_PAY_OFFSET:
 			A = __skb_get_poff(skb);
 			continue;
+		case BPF_S_ANC_MISSED_FLOW:
+			A = !!skb->missed_flow;
+			continue;
 		case BPF_S_ANC_NLATTR: {
 			struct nlattr *nla;
 
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [patch net-next RFC v2 3/6] openvswitch: split flow structures into ovs specific and generic ones
  2014-03-26 16:31 [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath Jiri Pirko
  2014-03-26 16:31 ` [patch net-next RFC v2 1/6] net: make packet_type->ak_packet_priv generic Jiri Pirko
  2014-03-26 16:31 ` [patch net-next RFC v2 2/6] skbuff: add "missed_flow" flag Jiri Pirko
@ 2014-03-26 16:31 ` Jiri Pirko
  2014-03-26 16:31 ` [patch net-next RFC v2 4/6] net: introduce switchdev API Jiri Pirko
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-26 16:31 UTC (permalink / raw
  To: netdev
  Cc: davem, nhorman, andy, tgraf, dborkman, ogerlitz, jesse, pshelar,
	azhou, ben, stephen, jeffrey.t.kirsher, vyasevic, xiyou.wangcong,
	john.r.fastabend, edumazet, jhs, sfeldma, f.fainelli, roopa,
	linville, dev

After this, flow related structures can be used in other code.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 include/linux/sw_flow.h        | 105 +++++++++++++++++++++++++++++++++++
 net/openvswitch/datapath.c     |  45 +++++++--------
 net/openvswitch/datapath.h     |   4 +-
 net/openvswitch/flow.c         |  14 ++---
 net/openvswitch/flow.h         | 123 +++++++++--------------------------------
 net/openvswitch/flow_netlink.c |  24 ++++----
 net/openvswitch/flow_netlink.h |   4 +-
 net/openvswitch/flow_table.c   | 100 +++++++++++++++++----------------
 net/openvswitch/flow_table.h   |  18 +++---
 net/openvswitch/vport-gre.c    |   4 +-
 net/openvswitch/vport-vxlan.c  |   2 +-
 net/openvswitch/vport.c        |   2 +-
 net/openvswitch/vport.h        |   2 +-
 13 files changed, 242 insertions(+), 205 deletions(-)
 create mode 100644 include/linux/sw_flow.h

diff --git a/include/linux/sw_flow.h b/include/linux/sw_flow.h
new file mode 100644
index 0000000..e7b1ef9
--- /dev/null
+++ b/include/linux/sw_flow.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2007-2012 Nicira, Inc.
+ * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
+ *
+ * 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 _LINUX_SW_FLOW_H_
+#define _LINUX_SW_FLOW_H_
+
+struct sw_flow_key_ipv4_tunnel {
+	__be64 tun_id;
+	__be32 ipv4_src;
+	__be32 ipv4_dst;
+	__be16 tun_flags;
+	u8   ipv4_tos;
+	u8   ipv4_ttl;
+};
+
+struct sw_flow_key {
+	struct sw_flow_key_ipv4_tunnel tun_key;  /* Encapsulating tunnel key. */
+	struct {
+		u32	priority;	/* Packet QoS priority. */
+		u32	skb_mark;	/* SKB mark. */
+		u16	in_port;	/* Input switch port (or DP_MAX_PORTS). */
+	} phy;
+	struct {
+		u8     src[ETH_ALEN];	/* Ethernet source address. */
+		u8     dst[ETH_ALEN];	/* Ethernet destination address. */
+		__be16 tci;		/* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
+		__be16 type;		/* Ethernet frame type. */
+	} eth;
+	struct {
+		u8     proto;		/* IP protocol or lower 8 bits of ARP opcode. */
+		u8     tos;		/* IP ToS. */
+		u8     ttl;		/* IP TTL/hop limit. */
+		u8     frag;		/* One of OVS_FRAG_TYPE_*. */
+	} ip;
+	union {
+		struct {
+			struct {
+				__be32 src;	/* IP source address. */
+				__be32 dst;	/* IP destination address. */
+			} addr;
+			union {
+				struct {
+					__be16 src;		/* TCP/UDP/SCTP source port. */
+					__be16 dst;		/* TCP/UDP/SCTP destination port. */
+					__be16 flags;		/* TCP flags. */
+				} tp;
+				struct {
+					u8 sha[ETH_ALEN];	/* ARP source hardware address. */
+					u8 tha[ETH_ALEN];	/* ARP target hardware address. */
+				} arp;
+			};
+		} ipv4;
+		struct {
+			struct {
+				struct in6_addr src;	/* IPv6 source address. */
+				struct in6_addr dst;	/* IPv6 destination address. */
+			} addr;
+			__be32 label;			/* IPv6 flow label. */
+			struct {
+				__be16 src;		/* TCP/UDP/SCTP source port. */
+				__be16 dst;		/* TCP/UDP/SCTP destination port. */
+				__be16 flags;		/* TCP flags. */
+			} tp;
+			struct {
+				struct in6_addr target;	/* ND target address. */
+				u8 sll[ETH_ALEN];	/* ND source link layer address. */
+				u8 tll[ETH_ALEN];	/* ND target link layer address. */
+			} nd;
+		} ipv6;
+	};
+} __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */
+
+struct sw_flow_key_range {
+	unsigned short int start;
+	unsigned short int end;
+};
+
+struct sw_flow_mask {
+	struct sw_flow_key_range range;
+	struct sw_flow_key key;
+};
+
+struct sw_flow {
+	struct sw_flow_key key;
+	struct sw_flow_key unmasked_key;
+	struct sw_flow_mask *mask;
+};
+
+#endif /* _LINUX_SW_FLOW_H_ */
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 48bbcd9..f229ab6 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -216,7 +216,7 @@ void ovs_dp_detach_port(struct vport *p)
 void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
 {
 	struct datapath *dp = p->dp;
-	struct sw_flow *flow;
+	struct ovs_flow *flow;
 	struct dp_stats_percpu *stats;
 	struct sw_flow_key key;
 	u64 *stats_counter;
@@ -488,7 +488,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 	struct nlattr **a = info->attrs;
 	struct sw_flow_actions *acts;
 	struct sk_buff *packet;
-	struct sw_flow *flow;
+	struct ovs_flow *flow;
 	struct datapath *dp;
 	struct ethhdr *eth;
 	int len;
@@ -525,11 +525,11 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 	if (IS_ERR(flow))
 		goto err_kfree_skb;
 
-	err = ovs_flow_extract(packet, -1, &flow->key);
+	err = ovs_flow_extract(packet, -1, &flow->flow.key);
 	if (err)
 		goto err_flow_free;
 
-	err = ovs_nla_get_flow_metadata(flow, a[OVS_PACKET_ATTR_KEY]);
+	err = ovs_nla_get_flow_metadata(&flow->flow, a[OVS_PACKET_ATTR_KEY]);
 	if (err)
 		goto err_flow_free;
 	acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_PACKET_ATTR_ACTIONS]));
@@ -538,15 +538,15 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 		goto err_flow_free;
 
 	err = ovs_nla_copy_actions(a[OVS_PACKET_ATTR_ACTIONS],
-				   &flow->key, 0, &acts);
+				   &flow->flow.key, 0, &acts);
 	rcu_assign_pointer(flow->sf_acts, acts);
 	if (err)
 		goto err_flow_free;
 
 	OVS_CB(packet)->flow = flow;
-	OVS_CB(packet)->pkt_key = &flow->key;
-	packet->priority = flow->key.phy.priority;
-	packet->mark = flow->key.phy.skb_mark;
+	OVS_CB(packet)->pkt_key = &flow->flow.key;
+	packet->priority = flow->flow.key.phy.priority;
+	packet->mark = flow->flow.key.phy.skb_mark;
 
 	rcu_read_lock();
 	dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
@@ -649,7 +649,7 @@ static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts)
 }
 
 /* Called with ovs_mutex. */
-static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
+static int ovs_flow_cmd_fill_info(struct ovs_flow *flow, struct datapath *dp,
 				  struct sk_buff *skb, u32 portid,
 				  u32 seq, u32 flags, u8 cmd)
 {
@@ -673,7 +673,8 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
 	if (!nla)
 		goto nla_put_failure;
 
-	err = ovs_nla_put_flow(&flow->unmasked_key, &flow->unmasked_key, skb);
+	err = ovs_nla_put_flow(&flow->flow.unmasked_key,
+			       &flow->flow.unmasked_key, skb);
 	if (err)
 		goto error;
 	nla_nest_end(skb, nla);
@@ -682,7 +683,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
 	if (!nla)
 		goto nla_put_failure;
 
-	err = ovs_nla_put_flow(&flow->key, &flow->mask->key, skb);
+	err = ovs_nla_put_flow(&flow->flow.key, &flow->flow.mask->key, skb);
 	if (err)
 		goto error;
 
@@ -739,7 +740,7 @@ error:
 	return err;
 }
 
-static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow,
+static struct sk_buff *ovs_flow_cmd_alloc_info(struct ovs_flow *flow,
 					       struct genl_info *info)
 {
 	size_t len;
@@ -749,7 +750,7 @@ static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow,
 	return genlmsg_new_unicast(len, info, GFP_KERNEL);
 }
 
-static struct sk_buff *ovs_flow_cmd_build_info(struct sw_flow *flow,
+static struct sk_buff *ovs_flow_cmd_build_info(struct ovs_flow *flow,
 					       struct datapath *dp,
 					       struct genl_info *info,
 					       u8 cmd)
@@ -772,12 +773,12 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 	struct nlattr **a = info->attrs;
 	struct ovs_header *ovs_header = info->userhdr;
 	struct sw_flow_key key, masked_key;
-	struct sw_flow *flow = NULL;
+	struct ovs_flow *flow = NULL;
 	struct sw_flow_mask mask;
 	struct sk_buff *reply;
 	struct datapath *dp;
 	struct sw_flow_actions *acts = NULL;
-	struct sw_flow_match match;
+	struct ovs_flow_match match;
 	bool exact_5tuple;
 	int error;
 
@@ -832,8 +833,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 			goto err_unlock_ovs;
 		}
 
-		flow->key = masked_key;
-		flow->unmasked_key = key;
+		flow->flow.key = masked_key;
+		flow->flow.unmasked_key = key;
 		rcu_assign_pointer(flow->sf_acts, acts);
 
 		/* Put flow in bucket. */
@@ -899,9 +900,9 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
 	struct ovs_header *ovs_header = info->userhdr;
 	struct sw_flow_key key;
 	struct sk_buff *reply;
-	struct sw_flow *flow;
+	struct ovs_flow *flow;
 	struct datapath *dp;
-	struct sw_flow_match match;
+	struct ovs_flow_match match;
 	int err;
 
 	if (!a[OVS_FLOW_ATTR_KEY]) {
@@ -946,9 +947,9 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
 	struct ovs_header *ovs_header = info->userhdr;
 	struct sw_flow_key key;
 	struct sk_buff *reply;
-	struct sw_flow *flow;
+	struct ovs_flow *flow;
 	struct datapath *dp;
-	struct sw_flow_match match;
+	struct ovs_flow_match match;
 	int err;
 
 	ovs_lock();
@@ -1011,7 +1012,7 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
 
 	ti = rcu_dereference(dp->table.ti);
 	for (;;) {
-		struct sw_flow *flow;
+		struct ovs_flow *flow;
 		u32 bucket, obj;
 
 		bucket = cb->args[0];
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index 0531738..5388cac 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -100,9 +100,9 @@ struct datapath {
  * packet is not being tunneled.
  */
 struct ovs_skb_cb {
-	struct sw_flow		*flow;
+	struct ovs_flow		*flow;
 	struct sw_flow_key	*pkt_key;
-	struct ovs_key_ipv4_tunnel  *tun_key;
+	struct sw_flow_key_ipv4_tunnel  *tun_key;
 };
 #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
 
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index dda451f..e0c326a 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -61,7 +61,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies)
 
 #define TCP_FLAGS_BE16(tp) (*(__be16 *)&tcp_flag_word(tp) & htons(0x0FFF))
 
-void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
+void ovs_flow_stats_update(struct ovs_flow *flow, struct sk_buff *skb)
 {
 	struct flow_stats *stats;
 	__be16 tcp_flags = 0;
@@ -71,10 +71,10 @@ void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
 	else
 		stats = this_cpu_ptr(flow->stats.cpu_stats);
 
-	if ((flow->key.eth.type == htons(ETH_P_IP) ||
-	     flow->key.eth.type == htons(ETH_P_IPV6)) &&
-	    flow->key.ip.frag != OVS_FRAG_TYPE_LATER &&
-	    flow->key.ip.proto == IPPROTO_TCP &&
+	if ((flow->flow.key.eth.type == htons(ETH_P_IP) ||
+	     flow->flow.key.eth.type == htons(ETH_P_IPV6)) &&
+	    flow->flow.key.ip.frag != OVS_FRAG_TYPE_LATER &&
+	    flow->flow.key.ip.proto == IPPROTO_TCP &&
 	    likely(skb->len >= skb_transport_offset(skb) + sizeof(struct tcphdr))) {
 		tcp_flags = TCP_FLAGS_BE16(tcp_hdr(skb));
 	}
@@ -100,7 +100,7 @@ static void stats_read(struct flow_stats *stats,
 	spin_unlock(&stats->lock);
 }
 
-void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats,
+void ovs_flow_stats_get(struct ovs_flow *flow, struct ovs_flow_stats *ovs_stats,
 			unsigned long *used, __be16 *tcp_flags)
 {
 	int cpu, cur_cpu;
@@ -139,7 +139,7 @@ static void stats_reset(struct flow_stats *stats)
 	spin_unlock(&stats->lock);
 }
 
-void ovs_flow_stats_clear(struct sw_flow *flow)
+void ovs_flow_stats_clear(struct ovs_flow *flow)
 {
 	int cpu, cur_cpu;
 
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 2d770e2..1ece896 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -32,24 +32,16 @@
 #include <linux/time.h>
 #include <linux/flex_array.h>
 #include <net/inet_ecn.h>
+#include <linux/sw_flow.h>
 
 struct sk_buff;
 
-/* Used to memset ovs_key_ipv4_tunnel padding. */
+/* Used to memset sw_flow_key_ipv4_tunnel padding. */
 #define OVS_TUNNEL_KEY_SIZE					\
-	(offsetof(struct ovs_key_ipv4_tunnel, ipv4_ttl) +	\
-	FIELD_SIZEOF(struct ovs_key_ipv4_tunnel, ipv4_ttl))
-
-struct ovs_key_ipv4_tunnel {
-	__be64 tun_id;
-	__be32 ipv4_src;
-	__be32 ipv4_dst;
-	__be16 tun_flags;
-	u8   ipv4_tos;
-	u8   ipv4_ttl;
-};
+	(offsetof(struct sw_flow_key_ipv4_tunnel, ipv4_ttl) +	\
+	FIELD_SIZEOF(struct sw_flow_key_ipv4_tunnel, ipv4_ttl))
 
-static inline void ovs_flow_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key,
+static inline void ovs_flow_tun_key_init(struct sw_flow_key_ipv4_tunnel *tun_key,
 					 const struct iphdr *iph, __be64 tun_id,
 					 __be16 tun_flags)
 {
@@ -65,77 +57,28 @@ static inline void ovs_flow_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key,
 	       sizeof(*tun_key) - OVS_TUNNEL_KEY_SIZE);
 }
 
-struct sw_flow_key {
-	struct ovs_key_ipv4_tunnel tun_key;  /* Encapsulating tunnel key. */
-	struct {
-		u32	priority;	/* Packet QoS priority. */
-		u32	skb_mark;	/* SKB mark. */
-		u16	in_port;	/* Input switch port (or DP_MAX_PORTS). */
-	} phy;
-	struct {
-		u8     src[ETH_ALEN];	/* Ethernet source address. */
-		u8     dst[ETH_ALEN];	/* Ethernet destination address. */
-		__be16 tci;		/* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
-		__be16 type;		/* Ethernet frame type. */
-	} eth;
-	struct {
-		u8     proto;		/* IP protocol or lower 8 bits of ARP opcode. */
-		u8     tos;		/* IP ToS. */
-		u8     ttl;		/* IP TTL/hop limit. */
-		u8     frag;		/* One of OVS_FRAG_TYPE_*. */
-	} ip;
-	union {
-		struct {
-			struct {
-				__be32 src;	/* IP source address. */
-				__be32 dst;	/* IP destination address. */
-			} addr;
-			union {
-				struct {
-					__be16 src;		/* TCP/UDP/SCTP source port. */
-					__be16 dst;		/* TCP/UDP/SCTP destination port. */
-					__be16 flags;		/* TCP flags. */
-				} tp;
-				struct {
-					u8 sha[ETH_ALEN];	/* ARP source hardware address. */
-					u8 tha[ETH_ALEN];	/* ARP target hardware address. */
-				} arp;
-			};
-		} ipv4;
-		struct {
-			struct {
-				struct in6_addr src;	/* IPv6 source address. */
-				struct in6_addr dst;	/* IPv6 destination address. */
-			} addr;
-			__be32 label;			/* IPv6 flow label. */
-			struct {
-				__be16 src;		/* TCP/UDP/SCTP source port. */
-				__be16 dst;		/* TCP/UDP/SCTP destination port. */
-				__be16 flags;		/* TCP flags. */
-			} tp;
-			struct {
-				struct in6_addr target;	/* ND target address. */
-				u8 sll[ETH_ALEN];	/* ND source link layer address. */
-				u8 tll[ETH_ALEN];	/* ND target link layer address. */
-			} nd;
-		} ipv6;
-	};
-} __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */
+struct arp_eth_header {
+	__be16      ar_hrd;	/* format of hardware address   */
+	__be16      ar_pro;	/* format of protocol address   */
+	unsigned char   ar_hln;	/* length of hardware address   */
+	unsigned char   ar_pln;	/* length of protocol address   */
+	__be16      ar_op;	/* ARP opcode (command)     */
 
-struct sw_flow_key_range {
-	unsigned short int start;
-	unsigned short int end;
-};
+	/* Ethernet+IPv4 specific members. */
+	unsigned char       ar_sha[ETH_ALEN];	/* sender hardware address  */
+	unsigned char       ar_sip[4];		/* sender IP address        */
+	unsigned char       ar_tha[ETH_ALEN];	/* target hardware address  */
+	unsigned char       ar_tip[4];		/* target IP address        */
+} __packed;
 
-struct sw_flow_mask {
+struct ovs_flow_mask {
 	int ref_count;
 	struct rcu_head rcu;
 	struct list_head list;
-	struct sw_flow_key_range range;
-	struct sw_flow_key key;
+	struct sw_flow_mask mask;
 };
 
-struct sw_flow_match {
+struct ovs_flow_match {
 	struct sw_flow_key *key;
 	struct sw_flow_key_range range;
 	struct sw_flow_mask *mask;
@@ -163,36 +106,20 @@ struct sw_flow_stats {
 	};
 };
 
-struct sw_flow {
+struct ovs_flow {
 	struct rcu_head rcu;
 	struct hlist_node hash_node[2];
 	u32 hash;
 
-	struct sw_flow_key key;
-	struct sw_flow_key unmasked_key;
-	struct sw_flow_mask *mask;
+	struct sw_flow flow;
 	struct sw_flow_actions __rcu *sf_acts;
 	struct sw_flow_stats stats;
 };
 
-struct arp_eth_header {
-	__be16      ar_hrd;	/* format of hardware address   */
-	__be16      ar_pro;	/* format of protocol address   */
-	unsigned char   ar_hln;	/* length of hardware address   */
-	unsigned char   ar_pln;	/* length of protocol address   */
-	__be16      ar_op;	/* ARP opcode (command)     */
-
-	/* Ethernet+IPv4 specific members. */
-	unsigned char       ar_sha[ETH_ALEN];	/* sender hardware address  */
-	unsigned char       ar_sip[4];		/* sender IP address        */
-	unsigned char       ar_tha[ETH_ALEN];	/* target hardware address  */
-	unsigned char       ar_tip[4];		/* target IP address        */
-} __packed;
-
-void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb);
-void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *stats,
+void ovs_flow_stats_update(struct ovs_flow *flow, struct sk_buff *skb);
+void ovs_flow_stats_get(struct ovs_flow *flow, struct ovs_flow_stats *stats,
 			unsigned long *used, __be16 *tcp_flags);
-void ovs_flow_stats_clear(struct sw_flow *flow);
+void ovs_flow_stats_clear(struct ovs_flow *flow);
 u64 ovs_flow_used_time(unsigned long flow_jiffies);
 
 int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *);
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 4d000ac..179ab98 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -46,7 +46,7 @@
 
 #include "flow_netlink.h"
 
-static void update_range__(struct sw_flow_match *match,
+static void update_range__(struct ovs_flow_match *match,
 			   size_t offset, size_t size, bool is_mask)
 {
 	struct sw_flow_key_range *range = NULL;
@@ -103,7 +103,7 @@ static u16 range_n_bytes(const struct sw_flow_key_range *range)
 	return range->end - range->start;
 }
 
-static bool match_validate(const struct sw_flow_match *match,
+static bool match_validate(const struct ovs_flow_match *match,
 			   u64 key_attrs, u64 mask_attrs)
 {
 	u64 key_expected = 1 << OVS_KEY_ATTR_ETHERNET;
@@ -339,7 +339,7 @@ static int parse_flow_nlattrs(const struct nlattr *attr,
 }
 
 static int ipv4_tun_from_nlattr(const struct nlattr *attr,
-				struct sw_flow_match *match, bool is_mask)
+				struct ovs_flow_match *match, bool is_mask)
 {
 	struct nlattr *a;
 	int rem;
@@ -428,8 +428,8 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
 }
 
 static int ipv4_tun_to_nlattr(struct sk_buff *skb,
-			      const struct ovs_key_ipv4_tunnel *tun_key,
-			      const struct ovs_key_ipv4_tunnel *output)
+			      const struct sw_flow_key_ipv4_tunnel *tun_key,
+			      const struct sw_flow_key_ipv4_tunnel *output)
 {
 	struct nlattr *nla;
 
@@ -463,7 +463,7 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb,
 }
 
 
-static int metadata_from_nlattrs(struct sw_flow_match *match,  u64 *attrs,
+static int metadata_from_nlattrs(struct ovs_flow_match *match,  u64 *attrs,
 				 const struct nlattr **a, bool is_mask)
 {
 	if (*attrs & (1 << OVS_KEY_ATTR_PRIORITY)) {
@@ -501,7 +501,7 @@ static int metadata_from_nlattrs(struct sw_flow_match *match,  u64 *attrs,
 	return 0;
 }
 
-static int ovs_key_from_nlattrs(struct sw_flow_match *match,  bool *exact_5tuple,
+static int ovs_key_from_nlattrs(struct ovs_flow_match *match,  bool *exact_5tuple,
 				u64 attrs, const struct nlattr **a,
 				bool is_mask)
 {
@@ -799,7 +799,7 @@ static void sw_flow_mask_set(struct sw_flow_mask *mask,
  * @mask: Optional. Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink
  * attribute specifies the mask field of the wildcarded flow.
  */
-int ovs_nla_get_match(struct sw_flow_match *match,
+int ovs_nla_get_match(struct ovs_flow_match *match,
 		      bool *exact_5tuple,
 		      const struct nlattr *key,
 		      const struct nlattr *mask)
@@ -922,11 +922,11 @@ int ovs_nla_get_match(struct sw_flow_match *match,
 int ovs_nla_get_flow_metadata(struct sw_flow *flow,
 			      const struct nlattr *attr)
 {
-	struct ovs_key_ipv4_tunnel *tun_key = &flow->key.tun_key;
+	struct sw_flow_key_ipv4_tunnel *tun_key = &flow->key.tun_key;
 	const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
 	u64 attrs = 0;
 	int err;
-	struct sw_flow_match match;
+	struct ovs_flow_match match;
 
 	flow->key.phy.in_port = DP_MAX_PORTS;
 	flow->key.phy.priority = 0;
@@ -1320,7 +1320,7 @@ static int validate_tp_port(const struct sw_flow_key *flow_key)
 	return -EINVAL;
 }
 
-void ovs_match_init(struct sw_flow_match *match,
+void ovs_match_init(struct ovs_flow_match *match,
 		    struct sw_flow_key *key,
 		    struct sw_flow_mask *mask)
 {
@@ -1339,7 +1339,7 @@ void ovs_match_init(struct sw_flow_match *match,
 static int validate_and_copy_set_tun(const struct nlattr *attr,
 				     struct sw_flow_actions **sfa)
 {
-	struct sw_flow_match match;
+	struct ovs_flow_match match;
 	struct sw_flow_key key;
 	int err, start;
 
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h
index b31fbe2..f223929 100644
--- a/net/openvswitch/flow_netlink.h
+++ b/net/openvswitch/flow_netlink.h
@@ -37,14 +37,14 @@
 
 #include "flow.h"
 
-void ovs_match_init(struct sw_flow_match *match,
+void ovs_match_init(struct ovs_flow_match *match,
 		    struct sw_flow_key *key, struct sw_flow_mask *mask);
 
 int ovs_nla_put_flow(const struct sw_flow_key *,
 		     const struct sw_flow_key *, struct sk_buff *);
 int ovs_nla_get_flow_metadata(struct sw_flow *flow,
 			      const struct nlattr *attr);
-int ovs_nla_get_match(struct sw_flow_match *match,
+int ovs_nla_get_match(struct ovs_flow_match *match,
 		      bool *exact_5tuple,
 		      const struct nlattr *,
 		      const struct nlattr *);
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c
index 3c268b3..053ece9 100644
--- a/net/openvswitch/flow_table.c
+++ b/net/openvswitch/flow_table.c
@@ -70,9 +70,9 @@ void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
 		*d++ = *s++ & *m++;
 }
 
-struct sw_flow *ovs_flow_alloc(bool percpu_stats)
+struct ovs_flow *ovs_flow_alloc(bool percpu_stats)
 {
-	struct sw_flow *flow;
+	struct ovs_flow *flow;
 	int cpu;
 
 	flow = kmem_cache_alloc(flow_cache, GFP_KERNEL);
@@ -80,7 +80,7 @@ struct sw_flow *ovs_flow_alloc(bool percpu_stats)
 		return ERR_PTR(-ENOMEM);
 
 	flow->sf_acts = NULL;
-	flow->mask = NULL;
+	flow->flow.mask = NULL;
 
 	flow->stats.is_percpu = percpu_stats;
 
@@ -136,7 +136,7 @@ static struct flex_array *alloc_buckets(unsigned int n_buckets)
 	return buckets;
 }
 
-static void flow_free(struct sw_flow *flow)
+static void flow_free(struct ovs_flow *flow)
 {
 	kfree((struct sf_flow_acts __force *)flow->sf_acts);
 	if (flow->stats.is_percpu)
@@ -148,18 +148,20 @@ static void flow_free(struct sw_flow *flow)
 
 static void rcu_free_flow_callback(struct rcu_head *rcu)
 {
-	struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu);
+	struct ovs_flow *flow = container_of(rcu, struct ovs_flow, rcu);
 
 	flow_free(flow);
 }
 
-void ovs_flow_free(struct sw_flow *flow, bool deferred)
+void ovs_flow_free(struct ovs_flow *flow, bool deferred)
 {
 	if (!flow)
 		return;
 
-	if (flow->mask) {
-		struct sw_flow_mask *mask = flow->mask;
+	if (flow->flow.mask) {
+		struct ovs_flow_mask *mask = container_of(flow->flow.mask,
+							  struct ovs_flow_mask,
+							  mask);
 
 		/* ovs-lock is required to protect mask-refcount and
 		 * mask list.
@@ -250,7 +252,7 @@ static void table_instance_destroy(struct table_instance *ti, bool deferred)
 		goto skip_flows;
 
 	for (i = 0; i < ti->n_buckets; i++) {
-		struct sw_flow *flow;
+		struct ovs_flow *flow;
 		struct hlist_head *head = flex_array_get(ti->buckets, i);
 		struct hlist_node *n;
 		int ver = ti->node_ver;
@@ -275,10 +277,10 @@ void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred)
 	table_instance_destroy(ti, deferred);
 }
 
-struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *ti,
+struct ovs_flow *ovs_flow_tbl_dump_next(struct table_instance *ti,
 				       u32 *bucket, u32 *last)
 {
-	struct sw_flow *flow;
+	struct ovs_flow *flow;
 	struct hlist_head *head;
 	int ver;
 	int i;
@@ -309,7 +311,8 @@ static struct hlist_head *find_bucket(struct table_instance *ti, u32 hash)
 				(hash & (ti->n_buckets - 1)));
 }
 
-static void table_instance_insert(struct table_instance *ti, struct sw_flow *flow)
+static void table_instance_insert(struct table_instance *ti,
+				  struct ovs_flow *flow)
 {
 	struct hlist_head *head;
 
@@ -328,7 +331,7 @@ static void flow_table_copy_flows(struct table_instance *old,
 
 	/* Insert in new table. */
 	for (i = 0; i < old->n_buckets; i++) {
-		struct sw_flow *flow;
+		struct ovs_flow *flow;
 		struct hlist_head *head;
 
 		head = flex_array_get(old->buckets, i);
@@ -415,21 +418,21 @@ static bool flow_cmp_masked_key(const struct sw_flow *flow,
 	return cmp_key(&flow->key, key, key_start, key_end);
 }
 
-bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
-			       struct sw_flow_match *match)
+bool ovs_flow_cmp_unmasked_key(const struct ovs_flow *flow,
+			       struct ovs_flow_match *match)
 {
 	struct sw_flow_key *key = match->key;
 	int key_start = flow_key_start(key);
 	int key_end = match->range.end;
 
-	return cmp_key(&flow->unmasked_key, key, key_start, key_end);
+	return cmp_key(&flow->flow.unmasked_key, key, key_start, key_end);
 }
 
-static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
-					  const struct sw_flow_key *unmasked,
-					  struct sw_flow_mask *mask)
+static struct ovs_flow *masked_flow_lookup(struct table_instance *ti,
+					   const struct sw_flow_key *unmasked,
+					   struct sw_flow_mask *mask)
 {
-	struct sw_flow *flow;
+	struct ovs_flow *flow;
 	struct hlist_head *head;
 	int key_start = mask->range.start;
 	int key_end = mask->range.end;
@@ -440,34 +443,34 @@ static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
 	hash = flow_hash(&masked_key, key_start, key_end);
 	head = find_bucket(ti, hash);
 	hlist_for_each_entry_rcu(flow, head, hash_node[ti->node_ver]) {
-		if (flow->mask == mask && flow->hash == hash &&
-		    flow_cmp_masked_key(flow, &masked_key,
+		if (flow->flow.mask == mask && flow->hash == hash &&
+		    flow_cmp_masked_key(&flow->flow, &masked_key,
 					  key_start, key_end))
 			return flow;
 	}
 	return NULL;
 }
 
-struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *tbl,
-				    const struct sw_flow_key *key,
-				    u32 *n_mask_hit)
+struct ovs_flow *ovs_flow_tbl_lookup_stats(struct flow_table *tbl,
+					   const struct sw_flow_key *key,
+					   u32 *n_mask_hit)
 {
 	struct table_instance *ti = rcu_dereference_ovsl(tbl->ti);
-	struct sw_flow_mask *mask;
-	struct sw_flow *flow;
+	struct ovs_flow_mask *mask;
+	struct ovs_flow *flow;
 
 	*n_mask_hit = 0;
 	list_for_each_entry_rcu(mask, &tbl->mask_list, list) {
 		(*n_mask_hit)++;
-		flow = masked_flow_lookup(ti, key, mask);
+		flow = masked_flow_lookup(ti, key, &mask->mask);
 		if (flow)  /* Found */
 			return flow;
 	}
 	return NULL;
 }
 
-struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
-				    const struct sw_flow_key *key)
+struct ovs_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
+				     const struct sw_flow_key *key)
 {
 	u32 __always_unused n_mask_hit;
 
@@ -476,7 +479,7 @@ struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
 
 int ovs_flow_tbl_num_masks(const struct flow_table *table)
 {
-	struct sw_flow_mask *mask;
+	struct ovs_flow_mask *mask;
 	int num = 0;
 
 	list_for_each_entry(mask, &table->mask_list, list)
@@ -490,7 +493,7 @@ static struct table_instance *table_instance_expand(struct table_instance *ti)
 	return table_instance_rehash(ti, ti->n_buckets * 2);
 }
 
-void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow)
+void ovs_flow_tbl_remove(struct flow_table *table, struct ovs_flow *flow)
 {
 	struct table_instance *ti = ovsl_dereference(table->ti);
 
@@ -499,9 +502,9 @@ void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow)
 	table->count--;
 }
 
-static struct sw_flow_mask *mask_alloc(void)
+static struct ovs_flow_mask *mask_alloc(void)
 {
-	struct sw_flow_mask *mask;
+	struct ovs_flow_mask *mask;
 
 	mask = kmalloc(sizeof(*mask), GFP_KERNEL);
 	if (mask)
@@ -521,15 +524,15 @@ static bool mask_equal(const struct sw_flow_mask *a,
 		&& (memcmp(a_, b_, range_n_bytes(&a->range)) == 0);
 }
 
-static struct sw_flow_mask *flow_mask_find(const struct flow_table *tbl,
-					   const struct sw_flow_mask *mask)
+static struct ovs_flow_mask *flow_mask_find(const struct flow_table *tbl,
+					    const struct sw_flow_mask *mask)
 {
 	struct list_head *ml;
 
 	list_for_each(ml, &tbl->mask_list) {
-		struct sw_flow_mask *m;
-		m = container_of(ml, struct sw_flow_mask, list);
-		if (mask_equal(mask, m))
+		struct ovs_flow_mask *m;
+		m = container_of(ml, struct ovs_flow_mask, list);
+		if (mask_equal(mask, &m->mask))
 			return m;
 	}
 
@@ -537,29 +540,30 @@ static struct sw_flow_mask *flow_mask_find(const struct flow_table *tbl,
 }
 
 /* Add 'mask' into the mask list, if it is not already there. */
-static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow,
+static int flow_mask_insert(struct flow_table *tbl, struct ovs_flow *flow,
 			    struct sw_flow_mask *new)
 {
-	struct sw_flow_mask *mask;
+	struct ovs_flow_mask *mask;
+
 	mask = flow_mask_find(tbl, new);
 	if (!mask) {
 		/* Allocate a new mask if none exsits. */
 		mask = mask_alloc();
 		if (!mask)
 			return -ENOMEM;
-		mask->key = new->key;
-		mask->range = new->range;
+		mask->mask.key = new->key;
+		mask->mask.range = new->range;
 		list_add_rcu(&mask->list, &tbl->mask_list);
 	} else {
 		BUG_ON(!mask->ref_count);
 		mask->ref_count++;
 	}
 
-	flow->mask = mask;
+	flow->flow.mask = &mask->mask;
 	return 0;
 }
 
-int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
+int ovs_flow_tbl_insert(struct flow_table *table, struct ovs_flow *flow,
 			struct sw_flow_mask *mask)
 {
 	struct table_instance *new_ti = NULL;
@@ -570,8 +574,8 @@ int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
 	if (err)
 		return err;
 
-	flow->hash = flow_hash(&flow->key, flow->mask->range.start,
-			flow->mask->range.end);
+	flow->hash = flow_hash(&flow->flow.key, flow->flow.mask->range.start,
+			        flow->flow.mask->range.end);
 	ti = ovsl_dereference(table->ti);
 	table_instance_insert(ti, flow);
 	table->count++;
@@ -597,7 +601,7 @@ int ovs_flow_init(void)
 	BUILD_BUG_ON(__alignof__(struct sw_flow_key) % __alignof__(long));
 	BUILD_BUG_ON(sizeof(struct sw_flow_key) % sizeof(long));
 
-	flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow), 0,
+	flow_cache = kmem_cache_create("ovs_flow", sizeof(struct ovs_flow), 0,
 					0, NULL);
 	if (flow_cache == NULL)
 		return -ENOMEM;
diff --git a/net/openvswitch/flow_table.h b/net/openvswitch/flow_table.h
index baaeb10..c6abd84 100644
--- a/net/openvswitch/flow_table.h
+++ b/net/openvswitch/flow_table.h
@@ -55,28 +55,28 @@ struct flow_table {
 int ovs_flow_init(void);
 void ovs_flow_exit(void);
 
-struct sw_flow *ovs_flow_alloc(bool percpu_stats);
-void ovs_flow_free(struct sw_flow *, bool deferred);
+struct ovs_flow *ovs_flow_alloc(bool percpu_stats);
+void ovs_flow_free(struct ovs_flow *, bool deferred);
 
 int ovs_flow_tbl_init(struct flow_table *);
 int ovs_flow_tbl_count(struct flow_table *table);
 void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred);
 int ovs_flow_tbl_flush(struct flow_table *flow_table);
 
-int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
+int ovs_flow_tbl_insert(struct flow_table *table, struct ovs_flow *flow,
 			struct sw_flow_mask *mask);
-void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow);
+void ovs_flow_tbl_remove(struct flow_table *table, struct ovs_flow *flow);
 int  ovs_flow_tbl_num_masks(const struct flow_table *table);
-struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *table,
+struct ovs_flow *ovs_flow_tbl_dump_next(struct table_instance *table,
 				       u32 *bucket, u32 *idx);
-struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *,
+struct ovs_flow *ovs_flow_tbl_lookup_stats(struct flow_table *,
 				    const struct sw_flow_key *,
 				    u32 *n_mask_hit);
-struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *,
+struct ovs_flow *ovs_flow_tbl_lookup(struct flow_table *,
 				    const struct sw_flow_key *);
 
-bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
-			       struct sw_flow_match *match);
+bool ovs_flow_cmp_unmasked_key(const struct ovs_flow *flow,
+			       struct ovs_flow_match *match);
 
 void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
 		       const struct sw_flow_mask *mask);
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index a3d6951..f940cbd 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -63,7 +63,7 @@ static __be16 filter_tnl_flags(__be16 flags)
 static struct sk_buff *__build_header(struct sk_buff *skb,
 				      int tunnel_hlen)
 {
-	const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
+	const struct sw_flow_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
 	struct tnl_ptk_info tpi;
 
 	skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM));
@@ -92,7 +92,7 @@ static __be64 key_to_tunnel_id(__be32 key, __be32 seq)
 static int gre_rcv(struct sk_buff *skb,
 		   const struct tnl_ptk_info *tpi)
 {
-	struct ovs_key_ipv4_tunnel tun_key;
+	struct sw_flow_key_ipv4_tunnel tun_key;
 	struct ovs_net *ovs_net;
 	struct vport *vport;
 	__be64 key;
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c
index e797a50..e0be18e 100644
--- a/net/openvswitch/vport-vxlan.c
+++ b/net/openvswitch/vport-vxlan.c
@@ -58,7 +58,7 @@ static inline struct vxlan_port *vxlan_vport(const struct vport *vport)
 /* Called with rcu_read_lock and BH disabled. */
 static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, __be32 vx_vni)
 {
-	struct ovs_key_ipv4_tunnel tun_key;
+	struct sw_flow_key_ipv4_tunnel tun_key;
 	struct vport *vport = vs->data;
 	struct iphdr *iph;
 	__be64 key;
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index 42c0f4a..81b083c 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -337,7 +337,7 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
  * skb->data should point to the Ethernet header.
  */
 void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
-		       struct ovs_key_ipv4_tunnel *tun_key)
+		       struct sw_flow_key_ipv4_tunnel *tun_key)
 {
 	struct pcpu_sw_netstats *stats;
 
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index d7e50a1..0979304 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -191,7 +191,7 @@ static inline struct vport *vport_from_priv(const void *priv)
 }
 
 void ovs_vport_receive(struct vport *, struct sk_buff *,
-		       struct ovs_key_ipv4_tunnel *);
+		       struct sw_flow_key_ipv4_tunnel *);
 
 /* List of statically compiled vport implementations.  Don't forget to also
  * add yours to the list at the top of vport.c. */
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [patch net-next RFC v2 4/6] net: introduce switchdev API
  2014-03-26 16:31 [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath Jiri Pirko
                   ` (2 preceding siblings ...)
  2014-03-26 16:31 ` [patch net-next RFC v2 3/6] openvswitch: split flow structures into ovs specific and generic ones Jiri Pirko
@ 2014-03-26 16:31 ` Jiri Pirko
  2014-03-27 11:23   ` Thomas Graf
       [not found]   ` <1395851472-10524-5-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
  2014-03-26 16:33 ` [patch iproute2 RFC v2] iproute: add support for dummyswport Jiri Pirko
       [not found] ` <1395851472-10524-1-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
  5 siblings, 2 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-26 16:31 UTC (permalink / raw
  To: netdev
  Cc: davem, nhorman, andy, tgraf, dborkman, ogerlitz, jesse, pshelar,
	azhou, ben, stephen, jeffrey.t.kirsher, vyasevic, xiyou.wangcong,
	john.r.fastabend, edumazet, jhs, sfeldma, f.fainelli, roopa,
	linville, dev

switchdev API is designed to allow kernel support for various switch
chips.

It is the responsibility of a driver to create netdevice instances which
represents every port and for the switch master itself. Driver uses
swdev_register and swportdev_register functions to make the core aware
of the fact these netdevices are representing switch and switch ports.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 include/linux/netdevice.h |  24 +++++++
 include/linux/switchdev.h |  30 ++++++++
 net/Kconfig               |  10 +++
 net/core/Makefile         |   1 +
 net/core/switchdev.c      | 172 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 237 insertions(+)
 create mode 100644 include/linux/switchdev.h
 create mode 100644 net/core/switchdev.c

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 6b70e6f..5ad80da 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -49,6 +49,8 @@
 
 #include <linux/netdev_features.h>
 #include <linux/neighbour.h>
+#include <linux/sw_flow.h>
+
 #include <uapi/linux/netdevice.h>
 
 struct netpoll_info;
@@ -998,6 +1000,18 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
  *	Callback to use for xmit over the accelerated station. This
  *	is used in place of ndo_start_xmit on accelerated net
  *	devices.
+ *
+ * int (*ndo_swdev_flow_insert)(struct net_device *dev,
+ *				struct sw_flow *flow);
+ *	Called to insert a flow into switch device. If driver does
+ *	not implement this, it is assumed that the hw does not have
+ *	a capability to work with flows.
+ *
+ * int (*ndo_swdev_flow_remove)(struct net_device *dev,
+ *				struct sw_flow *flow);
+ *	Called to remove a flow from switch device. If driver does
+ *	not implement this, it is assumed that the hw does not have
+ *	a capability to work with flows.
  */
 struct net_device_ops {
 	int			(*ndo_init)(struct net_device *dev);
@@ -1145,6 +1159,12 @@ struct net_device_ops {
 	netdev_tx_t		(*ndo_dfwd_start_xmit) (struct sk_buff *skb,
 							struct net_device *dev,
 							void *priv);
+#if IS_ENABLED(CONFIG_NET_SWITCHDEV)
+	int			(*ndo_swdev_flow_insert)(struct net_device *dev,
+							 struct sw_flow *flow);
+	int			(*ndo_swdev_flow_remove)(struct net_device *dev,
+							 struct sw_flow *flow);
+#endif
 };
 
 /**
@@ -1205,6 +1225,8 @@ enum netdev_priv_flags {
 	IFF_SUPP_NOFCS			= 1<<19,
 	IFF_LIVE_ADDR_CHANGE		= 1<<20,
 	IFF_MACVLAN			= 1<<21,
+	IFF_SWITCH			= 1<<22,
+	IFF_SWITCH_PORT			= 1<<23,
 };
 
 #define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
@@ -1229,6 +1251,8 @@ enum netdev_priv_flags {
 #define IFF_SUPP_NOFCS			IFF_SUPP_NOFCS
 #define IFF_LIVE_ADDR_CHANGE		IFF_LIVE_ADDR_CHANGE
 #define IFF_MACVLAN			IFF_MACVLAN
+#define IFF_SWITCH			IFF_SWITCH
+#define IFF_SWITCH_PORT			IFF_SWITCH_PORT
 
 /*
  *	The DEVICE structure.
diff --git a/include/linux/switchdev.h b/include/linux/switchdev.h
new file mode 100644
index 0000000..e4aeaba
--- /dev/null
+++ b/include/linux/switchdev.h
@@ -0,0 +1,30 @@
+/*
+ * include/linux/switchdev.h - Switch device API
+ * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef _LINUX_SWITCHDEV_H_
+#define _LINUX_SWITCHDEV_H_
+
+#include <linux/netdevice.h>
+#include <linux/sw_flow.h>
+
+bool swdev_dev_check(const struct net_device *dev);
+int swdev_flow_insert(struct net_device *dev, struct sw_flow *flow);
+int swdev_flow_remove(struct net_device *dev, struct sw_flow *flow);
+int __swdev_register(struct net_device *dev);
+int swdev_register(struct net_device *dev);
+void __swdev_unregister(struct net_device *dev);
+void swdev_unregister(struct net_device *dev);
+
+bool swportdev_dev_check(const struct net_device *dev);
+int __swportdev_register(struct net_device *port_dev, struct net_device *dev);
+int swportdev_register(struct net_device *port_dev, struct net_device *dev);
+void __swportdev_unregister(struct net_device *port_dev);
+void swportdev_unregister(struct net_device *port_dev);
+
+#endif /* _LINUX_SWITCHDEV_H_ */
diff --git a/net/Kconfig b/net/Kconfig
index e411046..e02ab8d 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -285,6 +285,16 @@ config NET_FLOW_LIMIT
 	  with many clients some protection against DoS by a single (spoofed)
 	  flow that greatly exceeds average workload.
 
+config NET_SWITCHDEV
+	tristate "Switch device"
+	depends on INET
+	---help---
+	  This module provides glue for hardware switch chips so they can be
+	  accessed from userspace via Open vSwitch Netlink API. 
+
+	  To compile this code as a module, choose M here: the
+	  module will be called pktgen.
+
 menu "Network testing"
 
 config NET_PKTGEN
diff --git a/net/core/Makefile b/net/core/Makefile
index 9628c20..426a619 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o
 obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += timestamping.o
 obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o
 obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o
+obj-$(CONFIG_NET_SWITCHDEV) += switchdev.o
diff --git a/net/core/switchdev.c b/net/core/switchdev.c
new file mode 100644
index 0000000..ccd4fbc
--- /dev/null
+++ b/net/core/switchdev.c
@@ -0,0 +1,172 @@
+/*
+ * net/core/switchdev.c - Switch device API
+ * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/switchdev.h>
+#include <net/rtnetlink.h>
+
+bool swdev_dev_check(const struct net_device *dev)
+{
+	return dev->priv_flags & IFF_SWITCH;
+}
+EXPORT_SYMBOL(swdev_dev_check);
+
+int swdev_flow_insert(struct net_device *dev, struct sw_flow *flow)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+
+	BUG_ON(!swdev_dev_check(dev));
+	if (!ops->ndo_swdev_flow_insert)
+		return -EOPNOTSUPP;
+	return ops->ndo_swdev_flow_insert(dev, flow);
+}
+EXPORT_SYMBOL(swdev_flow_insert);
+
+int swdev_flow_remove(struct net_device *dev, struct sw_flow *flow)
+{
+	const struct net_device_ops *ops = dev->netdev_ops;
+
+	BUG_ON(!swdev_dev_check(dev));
+	if (!ops->ndo_swdev_flow_remove)
+		return -EOPNOTSUPP;
+	return ops->ndo_swdev_flow_remove(dev, flow);
+}
+EXPORT_SYMBOL(swdev_flow_remove);
+
+int __swdev_register(struct net_device *dev)
+{
+	if (dev->priv_flags & IFF_SWITCH) {
+		netdev_err(dev, "Device is already registered as a switch device\n");
+		return -EBUSY;
+	}
+	dev->priv_flags |= IFF_SWITCH;
+	netdev_info(dev, "Switch device registered\n");
+	return 0;
+}
+EXPORT_SYMBOL(__swdev_register);
+
+int swdev_register(struct net_device *dev)
+{
+	int err;
+
+	rtnl_lock();
+	err = __swdev_register(dev);
+	rtnl_unlock();
+	return err;
+}
+EXPORT_SYMBOL(swdev_register);
+
+void __swdev_unregister(struct net_device *dev)
+{
+	dev->priv_flags |= IFF_SWITCH;
+	netdev_info(dev, "Switch device unregistered\n");
+}
+EXPORT_SYMBOL(__swdev_unregister);
+
+void swdev_unregister(struct net_device *dev)
+{
+	rtnl_lock();
+	__swdev_unregister(dev);
+	rtnl_unlock();
+}
+EXPORT_SYMBOL(swdev_unregister);
+
+
+bool swportdev_dev_check(const struct net_device *port_dev)
+{
+	return port_dev->priv_flags & IFF_SWITCH_PORT;
+}
+EXPORT_SYMBOL(swportdev_dev_check);
+
+static rx_handler_result_t swportdev_handle_frame(struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+
+	/* We don't care what comes from port device into rx path.
+	 * If there's something there, it is destined to ETH_P_ALL
+	 * handlers. So just consume it.
+	 */
+	dev_kfree_skb(skb);
+	return RX_HANDLER_CONSUMED;
+}
+
+int __swportdev_register(struct net_device *port_dev, struct net_device *dev)
+{
+	int err;
+
+	if (!(dev->priv_flags & IFF_SWITCH)) {
+		netdev_err(dev, "Device is not a switch device\n");
+		return -EINVAL;
+	}
+	if (port_dev->priv_flags & IFF_SWITCH_PORT) {
+		netdev_err(port_dev, "Device is already registered as a switch port\n");
+		return -EBUSY;
+	}
+	err = netdev_master_upper_dev_link(port_dev, dev);
+	if (err) {
+		netdev_err(dev, "Device %s failed to set upper link\n",
+			   port_dev->name);
+		return err;
+	}
+	err = netdev_rx_handler_register(port_dev, swportdev_handle_frame, NULL);
+	if (err) {
+		netdev_err(dev, "Device %s failed to register rx_handler\n",
+			   port_dev->name);
+		goto err_handler_register;
+	}
+	port_dev->priv_flags |= IFF_SWITCH_PORT;
+	netdev_info(port_dev, "Switch port device registered\n");
+	return 0;
+
+err_handler_register:
+	netdev_upper_dev_unlink(port_dev, dev);
+	return err;
+}
+EXPORT_SYMBOL(__swportdev_register);
+
+int swportdev_register(struct net_device *port_dev, struct net_device *dev)
+{
+	int err;
+
+	rtnl_lock();
+	err = __swportdev_register(port_dev, dev);
+	rtnl_unlock();
+	return err;
+}
+EXPORT_SYMBOL(swportdev_register);
+
+void __swportdev_unregister(struct net_device *port_dev)
+{
+	struct net_device *dev;
+
+	dev = netdev_master_upper_dev_get(port_dev);
+	BUG_ON(!dev);
+	port_dev->priv_flags &= ~IFF_SWITCH_PORT;
+	netdev_rx_handler_unregister(port_dev);
+	netdev_upper_dev_unlink(port_dev, dev);
+	netdev_info(port_dev, "Switch port device unregistered\n");
+}
+EXPORT_SYMBOL(__swportdev_unregister);
+
+void swportdev_unregister(struct net_device *port_dev)
+{
+	rtnl_lock();
+	__swportdev_unregister(port_dev);
+	rtnl_unlock();
+}
+EXPORT_SYMBOL(swportdev_unregister);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Jiri Pirko <jiri@resnulli.us>");
+MODULE_DESCRIPTION("Switch device API");
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [patch net-next RFC v2 5/6] openvswitch: Introduce support for switchdev based datapath
       [not found] ` <1395851472-10524-1-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
@ 2014-03-26 16:31   ` Jiri Pirko
  2014-03-26 16:31   ` [patch net-next RFC v2 6/6] net: introduce dummy switch Jiri Pirko
  2014-03-26 21:44   ` [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath Jamal Hadi Salim
  2 siblings, 0 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-26 16:31 UTC (permalink / raw
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, andy-QlMahl40kYEqcZcGjlUOXw,
	dev-yBygre7rU0TnMu66kgdUjQ, f.fainelli-Re5JQEeQqe8AvxtiuMwx3w,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w, ben-/+tVBieCtBitmTQ+vhA3Yw,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	jhs-jkUAjuhPggJWk0Htik3J/w, linville-2XuSBdqkA4R54TAoqtyWWQ,
	vyasevic-H+wXaHxf7aLQT0dZR+AlfA, nhorman-2XuSBdqkA4R54TAoqtyWWQ,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

Signed-off-by: Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
---
 include/uapi/linux/openvswitch.h           |   4 +
 net/openvswitch/Makefile                   |   4 +
 net/openvswitch/datapath.c                 |  45 ++++++-
 net/openvswitch/datapath.h                 |   8 ++
 net/openvswitch/dp_notify.c                |   3 +-
 net/openvswitch/vport-internal_switchdev.c | 179 +++++++++++++++++++++++++
 net/openvswitch/vport-internal_switchdev.h |  28 ++++
 net/openvswitch/vport-netdev.c             |   4 +-
 net/openvswitch/vport-switchportdev.c      | 205 +++++++++++++++++++++++++++++
 net/openvswitch/vport-switchportdev.h      |  24 ++++
 net/openvswitch/vport.c                    |   4 +
 net/openvswitch/vport.h                    |   2 +
 12 files changed, 504 insertions(+), 6 deletions(-)
 create mode 100644 net/openvswitch/vport-internal_switchdev.c
 create mode 100644 net/openvswitch/vport-internal_switchdev.h
 create mode 100644 net/openvswitch/vport-switchportdev.c
 create mode 100644 net/openvswitch/vport-switchportdev.h

diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 970553c..8df1a49 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -189,6 +189,10 @@ enum ovs_vport_type {
 	OVS_VPORT_TYPE_INTERNAL, /* network device implemented by datapath */
 	OVS_VPORT_TYPE_GRE,      /* GRE tunnel. */
 	OVS_VPORT_TYPE_VXLAN,	 /* VXLAN tunnel. */
+	OVS_VPORT_TYPE_INTERNAL_SWITCHDEV, /* network device which represents
+					      a hardware switch */
+	OVS_VPORT_TYPE_SWITCHPORTDEV, /* network device which represents
+					 a port of a hardware switch */
 	__OVS_VPORT_TYPE_MAX
 };
 
diff --git a/net/openvswitch/Makefile b/net/openvswitch/Makefile
index 3591cb5..6e9fb2a 100644
--- a/net/openvswitch/Makefile
+++ b/net/openvswitch/Makefile
@@ -22,3 +22,7 @@ endif
 ifneq ($(CONFIG_OPENVSWITCH_GRE),)
 openvswitch-y += vport-gre.o
 endif
+
+ifneq ($(CONFIG_NET_SWITCHDEV),)
+openvswitch-y += vport-internal_switchdev.o vport-switchportdev.o
+endif
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index f229ab6..6056325 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -58,7 +58,9 @@
 #include "flow_table.h"
 #include "flow_netlink.h"
 #include "vport-internal_dev.h"
+#include "vport-internal_switchdev.h"
 #include "vport-netdev.h"
+#include "vport-switchportdev.h"
 
 int ovs_net_id __read_mostly;
 
@@ -124,6 +126,9 @@ static struct datapath *get_dp(struct net *net, int dp_ifindex)
 	dev = dev_get_by_index_rcu(net, dp_ifindex);
 	if (dev) {
 		struct vport *vport = ovs_internal_dev_get_vport(dev);
+
+		if (!vport)
+			vport = ovs_internal_swdev_get_vport(dev);
 		if (vport)
 			dp = vport->dp;
 	}
@@ -768,6 +773,19 @@ static struct sk_buff *ovs_flow_cmd_build_info(struct ovs_flow *flow,
 	return skb;
 }
 
+static int ovs_dp_flow_insert(struct datapath *dp, struct sw_flow *flow)
+{
+	if (dp->ops && dp->ops->flow_insert)
+		return dp->ops->flow_insert(dp, flow);
+	return 0;
+}
+
+static void ovs_dp_flow_remove(struct datapath *dp, struct sw_flow *flow)
+{
+	if (dp->ops && dp->ops->flow_remove)
+		dp->ops->flow_remove(dp, flow);
+}
+
 static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 {
 	struct nlattr **a = info->attrs;
@@ -836,13 +854,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_dp_flow_insert(dp, &flow->flow);
+		if (error)
+			goto err_flow_tbl_remove;
 
 		reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
 	} else {
@@ -884,6 +904,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:
@@ -981,6 +1003,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
 		goto unlock;
 	}
 
+	ovs_dp_flow_remove(dp, &flow->flow);
 	ovs_flow_tbl_remove(&dp->table, flow);
 
 	err = ovs_flow_cmd_fill_info(flow, dp, reply, info->snd_portid,
@@ -1234,7 +1257,10 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
 
 	/* Set up our datapath device. */
 	parms.name = nla_data(a[OVS_DP_ATTR_NAME]);
-	parms.type = OVS_VPORT_TYPE_INTERNAL;
+	if (ovs_is_suitable_for_internal_swdev(sock_net(skb->sk), parms.name))
+		parms.type = OVS_VPORT_TYPE_INTERNAL_SWITCHDEV;
+	else
+		parms.type = OVS_VPORT_TYPE_INTERNAL;
 	parms.options = NULL;
 	parms.dp = dp;
 	parms.port_no = OVSP_LOCAL;
@@ -1572,6 +1598,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
 	struct sk_buff *reply;
 	struct vport *vport;
 	struct datapath *dp;
+	struct vport *local_vport;
 	u32 port_no;
 	int err;
 
@@ -1611,6 +1638,16 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
 
 	parms.name = nla_data(a[OVS_VPORT_ATTR_NAME]);
 	parms.type = nla_get_u32(a[OVS_VPORT_ATTR_TYPE]);
+
+	if (parms.type == OVS_VPORT_TYPE_NETDEV &&
+	    ovs_is_suitable_for_switchportdev(sock_net(skb->sk), parms.name))
+		parms.type = OVS_VPORT_TYPE_SWITCHPORTDEV;
+
+	local_vport = ovs_vport_ovsl(dp, OVSP_LOCAL);
+	if (local_vport->ops->type == OVS_VPORT_TYPE_INTERNAL_SWITCHDEV &&
+	    parms.type != OVS_VPORT_TYPE_SWITCHPORTDEV)
+		return -EOPNOTSUPP;
+
 	parms.options = a[OVS_VPORT_ATTR_OPTIONS];
 	parms.dp = dp;
 	parms.port_no = port_no;
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index 5388cac..584999b 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -58,6 +58,8 @@ struct dp_stats_percpu {
 	struct u64_stats_sync syncp;
 };
 
+struct dp_ops;
+
 /**
  * struct datapath - datapath for flow-based packet switching
  * @rcu: RCU callback head for deferred destruction.
@@ -90,6 +92,12 @@ struct datapath {
 #endif
 
 	u32 user_features;
+	const struct dp_ops *ops;
+};
+
+struct dp_ops {
+	int (*flow_insert)(struct datapath *dp, struct sw_flow *flow);
+	void (*flow_remove)(struct datapath *dp, struct sw_flow *flow);
 };
 
 /**
diff --git a/net/openvswitch/dp_notify.c b/net/openvswitch/dp_notify.c
index 2c631fe..7f9b6ae 100644
--- a/net/openvswitch/dp_notify.c
+++ b/net/openvswitch/dp_notify.c
@@ -22,6 +22,7 @@
 
 #include "datapath.h"
 #include "vport-internal_dev.h"
+#include "vport-internal_switchdev.h"
 #include "vport-netdev.h"
 
 static void dp_detach_port_notify(struct vport *vport)
@@ -79,7 +80,7 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event,
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 	struct vport *vport = NULL;
 
-	if (!ovs_is_internal_dev(dev))
+	if (!ovs_is_internal_dev(dev) && !ovs_is_internal_swdev(dev))
 		vport = ovs_netdev_get_vport(dev);
 
 	if (!vport)
diff --git a/net/openvswitch/vport-internal_switchdev.c b/net/openvswitch/vport-internal_switchdev.c
new file mode 100644
index 0000000..e11547f
--- /dev/null
+++ b/net/openvswitch/vport-internal_switchdev.c
@@ -0,0 +1,179 @@
+/*
+ * 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/skbuff.h>
+#include <linux/switchdev.h>
+
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
+#include "datapath.h"
+#include "vport-netdev.h"
+#include "vport-internal_switchdev.h"
+
+static int internal_swdev_flow_insert(struct datapath *dp, struct sw_flow *flow)
+{
+	struct vport *vport;
+	struct netdev_vport *netdev_vport;
+
+	vport = ovs_vport_ovsl(dp, OVSP_LOCAL);
+	netdev_vport = netdev_vport_priv(vport);
+	return swdev_flow_insert(netdev_vport->dev, flow);
+}
+
+static void internal_swdev_flow_remove(struct datapath *dp, struct sw_flow *flow)
+{
+	struct vport *vport;
+	struct netdev_vport *netdev_vport;
+
+	vport = ovs_vport_ovsl(dp, OVSP_LOCAL);
+	netdev_vport = netdev_vport_priv(vport);
+	swdev_flow_remove(netdev_vport->dev, flow);
+}
+
+static const struct dp_ops internal_swdev_dp_ops = {
+	.flow_insert = internal_swdev_flow_insert,
+	.flow_remove = internal_swdev_flow_remove,
+};
+
+static struct vport *internal_swdev_create(const struct vport_parms *parms)
+{
+	struct vport *vport;
+	struct netdev_vport *netdev_vport;
+	struct net_device *dev;
+	int err;
+
+	vport = ovs_vport_alloc(sizeof(struct netdev_vport),
+				&ovs_internal_swdev_vport_ops, parms);
+	if (IS_ERR(vport))
+		return vport;
+
+	netdev_vport = netdev_vport_priv(vport);
+
+	rtnl_lock();
+	dev = __dev_get_by_name(ovs_dp_get_net(vport->dp), parms->name);
+	if (!dev) {
+		err = -ENODEV;
+		goto error_free_vport;
+	}
+	if (!swdev_dev_check(dev)) {
+		err = -EINVAL;
+		goto error_free_vport;
+	}
+	netdev_vport->dev = dev;
+	vport->dp->ops = &internal_swdev_dp_ops;
+	dev_hold(dev);
+	rtnl_unlock();
+
+	return vport;
+
+error_free_vport:
+	rtnl_unlock();
+	ovs_vport_free(vport);
+	return ERR_PTR(err);
+}
+
+static void internal_swdev_free_rcu(struct rcu_head *rcu)
+{
+	struct netdev_vport *netdev_vport;
+
+	netdev_vport = container_of(rcu, struct netdev_vport, rcu);
+	ovs_vport_free(vport_from_priv(netdev_vport));
+}
+
+static void internal_swdev_destroy(struct vport *vport)
+{
+	struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
+
+	dev_put(netdev_vport->dev);
+	call_rcu(&netdev_vport->rcu, internal_swdev_free_rcu);
+}
+
+static int internal_swdev_send(struct vport *vport, struct sk_buff *skb)
+{
+	int len;
+
+	len = skb->len;
+	consume_skb(skb);
+	return len;
+}
+
+const struct vport_ops ovs_internal_swdev_vport_ops = {
+	.type		= OVS_VPORT_TYPE_INTERNAL_SWITCHDEV,
+	.create		= internal_swdev_create,
+	.destroy	= internal_swdev_destroy,
+	.get_name	= ovs_netdev_get_name,
+	.send		= internal_swdev_send,
+};
+
+bool ovs_is_suitable_for_internal_swdev(struct net *net, const char *name)
+{
+	struct net_device *dev;
+	bool ret;
+
+	rcu_read_lock();
+	dev = dev_get_by_name_rcu(net, name);
+	ret = dev ? swdev_dev_check(dev) : false;
+	rcu_read_unlock();
+	return ret;
+}
+
+struct vport *ovs_internal_swdev_get_vport_by_dp(const struct datapath *dp)
+{
+	struct vport *vport;
+
+	vport = ovs_vport_rcu(dp, OVSP_LOCAL);
+	if (vport->ops->type != OVS_VPORT_TYPE_INTERNAL_SWITCHDEV)
+		return NULL;
+	return vport;
+}
+
+struct vport *ovs_internal_swdev_get_vport(const struct net_device *dev)
+{
+	struct ovs_net *ovs_net = net_generic(dev_net(dev), ovs_net_id);
+	struct datapath *dp;
+	struct vport *vport = NULL;
+
+	if (!swdev_dev_check(dev))
+		return NULL;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(dp, &ovs_net->dps, list_node) {
+		vport = ovs_internal_swdev_get_vport_by_dp(dp);
+		if (vport && netdev_vport_priv(vport)->dev == dev)
+			break;
+		vport = NULL;
+	}
+	rcu_read_unlock();
+	return vport;
+}
+
+bool ovs_is_internal_swdev(const struct net_device *dev)
+{
+	return ovs_internal_swdev_get_vport(dev) ? true : false;
+}
+
+struct net_device *ovs_internal_swdev_get_netdev(struct vport *vport)
+{
+	struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
+
+	return netdev_vport->dev;
+}
diff --git a/net/openvswitch/vport-internal_switchdev.h b/net/openvswitch/vport-internal_switchdev.h
new file mode 100644
index 0000000..7f320ff
--- /dev/null
+++ b/net/openvswitch/vport-internal_switchdev.h
@@ -0,0 +1,28 @@
+/*
+ * 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 VPORT_INTERNAL_SWITCHDEV_H
+#define VPORT_INTERNAL_SWITCHDEV_H 1
+
+bool ovs_is_suitable_for_internal_swdev(struct net *net, const char *name);
+struct vport *ovs_internal_swdev_get_vport_by_dp(const struct datapath *dp);
+struct vport *ovs_internal_swdev_get_vport(const struct net_device *dev);
+bool ovs_is_internal_swdev(const struct net_device *dev);
+struct net_device *ovs_internal_swdev_get_netdev(struct vport *vport);
+
+#endif /* vport-internal_switchdev.h */
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index d21f77d..3121b59 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -31,6 +31,7 @@
 
 #include "datapath.h"
 #include "vport-internal_dev.h"
+#include "vport-internal_switchdev.h"
 #include "vport-netdev.h"
 
 /* Must be called with rcu_read_lock. */
@@ -107,7 +108,8 @@ static struct vport *netdev_create(const struct vport_parms *parms)
 
 	if (netdev_vport->dev->flags & IFF_LOOPBACK ||
 	    netdev_vport->dev->type != ARPHRD_ETHER ||
-	    ovs_is_internal_dev(netdev_vport->dev)) {
+	    ovs_is_internal_dev(netdev_vport->dev) ||
+	    ovs_is_internal_swdev(netdev_vport->dev)) {
 		err = -EINVAL;
 		goto error_put;
 	}
diff --git a/net/openvswitch/vport-switchportdev.c b/net/openvswitch/vport-switchportdev.c
new file mode 100644
index 0000000..8657065
--- /dev/null
+++ b/net/openvswitch/vport-switchportdev.c
@@ -0,0 +1,205 @@
+/*
+ * 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/skbuff.h>
+#include <linux/if_vlan.h>
+#include <linux/switchdev.h>
+
+#include <net/net_namespace.h>
+
+#include "datapath.h"
+#include "vport-internal_switchdev.h"
+
+struct swportdev_vport {
+	struct rcu_head rcu;
+	struct net_device *dev;
+	struct packet_type pt;
+};
+
+static inline struct swportdev_vport *swportdev_vport_priv(const struct vport *vport)
+{
+	return vport_priv(vport);
+}
+
+static int vport_swportdev_rcv(struct sk_buff *skb, struct net_device *dev,
+			       struct packet_type *pt,
+			       struct net_device *orig_dev)
+{
+	struct vport *vport = pt->priv;
+	struct dp_upcall_info upcall;
+	struct sw_flow_key key;
+	int err;
+
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb)
+		return NET_RX_DROP;
+
+	if (!skb->missed_flow || skb->pkt_type == PACKET_OUTGOING)
+		goto drop;
+
+	/* Extract flow from 'skb' into 'key'. */
+	err = ovs_flow_extract(skb, vport->port_no, &key);
+	if (unlikely(err))
+		goto drop;
+
+	upcall.cmd = OVS_PACKET_CMD_MISS;
+	upcall.key = &key;
+	upcall.userdata = NULL;
+	upcall.portid = vport->upcall_portid;
+	ovs_dp_upcall(vport->dp, skb, &upcall);
+	consume_skb(skb);
+	return NET_RX_SUCCESS;
+
+drop:
+	consume_skb(skb);
+	return NET_RX_DROP;
+}
+
+static struct vport *vport_swportdev_create(const struct vport_parms *parms)
+{
+	struct vport *vport;
+	struct vport *swdev_vport;
+	struct swportdev_vport *swportdev_vport;
+	struct net_device *dev;
+	int err;
+
+	swdev_vport = ovs_internal_swdev_get_vport_by_dp(parms->dp);
+	if (!swdev_vport)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	vport = ovs_vport_alloc(sizeof(struct swportdev_vport),
+				&ovs_swportdev_vport_ops, parms);
+	if (IS_ERR(vport))
+		return vport;
+
+	swportdev_vport = swportdev_vport_priv(vport);
+
+	rtnl_lock();
+	dev = __dev_get_by_name(ovs_dp_get_net(vport->dp), parms->name);
+	if (!dev) {
+		err = -ENODEV;
+		goto error_free_vport;
+	}
+	if (!swportdev_dev_check(dev)) {
+		err = -EINVAL;
+		goto error_free_vport;
+	}
+	if (netdev_master_upper_dev_get(dev) !=
+	    ovs_internal_swdev_get_netdev(swdev_vport)) {
+		err = -EINVAL;
+		goto error_free_vport;
+	}
+
+	dev_hold(dev);
+	rtnl_unlock();
+	swportdev_vport->dev = dev;
+	swportdev_vport->pt.type = cpu_to_be16(ETH_P_ALL),
+	swportdev_vport->pt.dev = dev;
+	swportdev_vport->pt.func = vport_swportdev_rcv;
+	swportdev_vport->pt.priv = vport;
+	dev_add_pack(&swportdev_vport->pt);
+
+	return vport;
+
+error_free_vport:
+	rtnl_unlock();
+	ovs_vport_free(vport);
+	return ERR_PTR(err);
+}
+
+static void vport_swportdev_free_rcu(struct rcu_head *rcu)
+{
+	struct swportdev_vport *swportdev_vport;
+
+	swportdev_vport = container_of(rcu, struct swportdev_vport, rcu);
+	ovs_vport_free(vport_from_priv(swportdev_vport));
+}
+
+static void vport_swportdev_destroy(struct vport *vport)
+{
+	struct swportdev_vport *swportdev_vport = swportdev_vport_priv(vport);
+
+	__dev_remove_pack(&swportdev_vport->pt);
+	dev_put(swportdev_vport->dev);
+	call_rcu(&swportdev_vport->rcu, vport_swportdev_free_rcu);
+}
+
+static unsigned int packet_length(const struct sk_buff *skb)
+{
+	unsigned int length = skb->len - ETH_HLEN;
+
+	if (skb->protocol == htons(ETH_P_8021Q))
+		length -= VLAN_HLEN;
+
+	return length;
+}
+
+static int vport_swportdev_send(struct vport *vport, struct sk_buff *skb)
+{
+	struct swportdev_vport *swportdev_vport = swportdev_vport_priv(vport);
+	struct net_device *dev = swportdev_vport->dev;
+	int mtu = dev->mtu;
+	int len;
+
+	if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
+		net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
+				     dev->name, packet_length(skb), mtu);
+		goto drop;
+	}
+
+	skb->dev = dev;
+	len = skb->len;
+	dev_queue_xmit(skb);
+
+	return len;
+
+drop:
+	kfree_skb(skb);
+	return 0;
+}
+
+static const char *vport_swportdev_get_name(const struct vport *vport)
+{
+	struct swportdev_vport *swportdev_vport = swportdev_vport_priv(vport);
+
+	return swportdev_vport->dev->name;
+}
+
+const struct vport_ops ovs_swportdev_vport_ops = {
+	.type		= OVS_VPORT_TYPE_SWITCHPORTDEV,
+	.create		= vport_swportdev_create,
+	.destroy	= vport_swportdev_destroy,
+	.get_name	= vport_swportdev_get_name,
+	.send		= vport_swportdev_send,
+};
+
+bool ovs_is_suitable_for_switchportdev(struct net *net, const char *name)
+{
+	struct net_device *dev;
+	bool ret;
+
+	rcu_read_lock();
+	dev = dev_get_by_name_rcu(net, name);
+	ret = dev ? swportdev_dev_check(dev) : false;
+	rcu_read_unlock();
+	return ret;
+}
+
diff --git a/net/openvswitch/vport-switchportdev.h b/net/openvswitch/vport-switchportdev.h
new file mode 100644
index 0000000..b578794
--- /dev/null
+++ b/net/openvswitch/vport-switchportdev.h
@@ -0,0 +1,24 @@
+/*
+ * 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 VPORT_SWITCHPORTDEV_H
+#define VPORT_SWITCHPORTDEV_H 1
+
+bool ovs_is_suitable_for_switchportdev(struct net *net, const char *name);
+
+#endif /* vport-switchportdev.h */
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index 81b083c..39aa836 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -48,6 +48,10 @@ static const struct vport_ops *vport_ops_list[] = {
 #ifdef CONFIG_OPENVSWITCH_VXLAN
 	&ovs_vxlan_vport_ops,
 #endif
+#if IS_ENABLED(CONFIG_NET_SWITCHDEV)
+	&ovs_internal_swdev_vport_ops,
+	&ovs_swportdev_vport_ops,
+#endif
 };
 
 /* Protected by RCU read lock for reading, ovs_mutex for writing. */
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index 0979304..100277f 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -199,6 +199,8 @@ extern const struct vport_ops ovs_netdev_vport_ops;
 extern const struct vport_ops ovs_internal_vport_ops;
 extern const struct vport_ops ovs_gre_vport_ops;
 extern const struct vport_ops ovs_vxlan_vport_ops;
+extern const struct vport_ops ovs_internal_swdev_vport_ops;
+extern const struct vport_ops ovs_swportdev_vport_ops;
 
 static inline void ovs_skb_postpush_rcsum(struct sk_buff *skb,
 				      const void *start, unsigned int len)
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [patch net-next RFC v2 6/6] net: introduce dummy switch
       [not found] ` <1395851472-10524-1-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
  2014-03-26 16:31   ` [patch net-next RFC v2 5/6] openvswitch: Introduce support for switchdev based datapath Jiri Pirko
@ 2014-03-26 16:31   ` Jiri Pirko
  2014-03-26 21:44   ` [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath Jamal Hadi Salim
  2 siblings, 0 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-26 16:31 UTC (permalink / raw
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, andy-QlMahl40kYEqcZcGjlUOXw,
	dev-yBygre7rU0TnMu66kgdUjQ, f.fainelli-Re5JQEeQqe8AvxtiuMwx3w,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w, ben-/+tVBieCtBitmTQ+vhA3Yw,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	jhs-jkUAjuhPggJWk0Htik3J/w, linville-2XuSBdqkA4R54TAoqtyWWQ,
	vyasevic-H+wXaHxf7aLQT0dZR+AlfA, nhorman-2XuSBdqkA4R54TAoqtyWWQ,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

Dummy switch implementation using switchdev API

Signed-off-by: Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
---
 drivers/net/Kconfig          |   7 ++
 drivers/net/Makefile         |   1 +
 drivers/net/dummyswitch.c    | 235 +++++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/if_link.h |   9 ++
 4 files changed, 252 insertions(+)
 create mode 100644 drivers/net/dummyswitch.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 89402c3..a9629a7 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -71,6 +71,13 @@ config DUMMY
 	  To compile this driver as a module, choose M here: the module
 	  will be called dummy.
 
+config NET_DUMMY_SWITCH
+	tristate "Dummy switch net driver support"
+	depends on NET_SWITCHDEV
+	---help---
+	  To compile this driver as a module, choose M here: the module
+	  will be called dummyswitch.
+
 config EQUALIZER
 	tristate "EQL (serial line load balancing) support"
 	---help---
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 3fef8a8..d5d4ce6 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -7,6 +7,7 @@
 #
 obj-$(CONFIG_BONDING) += bonding/
 obj-$(CONFIG_DUMMY) += dummy.o
+obj-$(CONFIG_NET_DUMMY_SWITCH) += dummyswitch.o
 obj-$(CONFIG_EQUALIZER) += eql.o
 obj-$(CONFIG_IFB) += ifb.o
 obj-$(CONFIG_MACVLAN) += macvlan.o
diff --git a/drivers/net/dummyswitch.c b/drivers/net/dummyswitch.c
new file mode 100644
index 0000000..58c65a9
--- /dev/null
+++ b/drivers/net/dummyswitch.c
@@ -0,0 +1,235 @@
+/*
+ * drivers/net/dummyswitch.c - Dummy switch device
+ * 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 the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/etherdevice.h>
+#include <linux/switchdev.h>
+
+#include <net/rtnetlink.h>
+
+/*
+ * Dummy switch
+ */
+
+static void dummysw_uninit(struct net_device *dev)
+{
+	__swdev_unregister(dev);
+}
+
+static netdev_tx_t dummysw_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+static int dummysw_flow_insert(struct net_device *dev, struct sw_flow *flow)
+{
+	netdev_dbg(dev, "Flow inserted");
+	return 0;
+}
+static int dummysw_flow_remove(struct net_device *dev, struct sw_flow *flow)
+{
+	netdev_dbg(dev, "Flow removed");
+	return 0;
+}
+
+static const struct net_device_ops dummysw_netdev_ops = {
+	.ndo_uninit		= dummysw_uninit,
+	.ndo_start_xmit		= dummysw_xmit,
+	.ndo_swdev_flow_insert	= dummysw_flow_insert,
+	.ndo_swdev_flow_remove	= dummysw_flow_remove,
+};
+
+static void dummysw_setup(struct net_device *dev)
+{
+	ether_setup(dev);
+
+	/* Initialize the device structure. */
+	dev->netdev_ops = &dummysw_netdev_ops;
+	dev->destructor = free_netdev;
+
+	/* Fill in device structure with ethernet-generic values. */
+	dev->tx_queue_len = 0;
+	dev->flags |= IFF_NOARP;
+	dev->flags &= ~IFF_MULTICAST;
+	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+	dev->features	|= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO;
+	dev->features	|= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
+	eth_hw_addr_random(dev);
+}
+
+static int dummysw_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+	if (tb[IFLA_ADDRESS]) {
+		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+			return -EINVAL;
+		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+			return -EADDRNOTAVAIL;
+	}
+	return 0;
+}
+
+static int dummysw_newlink(struct net *src_net, struct net_device *dev,
+			   struct nlattr *tb[], struct nlattr *data[])
+{
+	int err;
+
+	err = register_netdevice(dev);
+	if (err)
+		return err;
+	err = __swdev_register(dev);
+	if (err)
+		goto err_swdev_register;
+	netif_carrier_on(dev);
+	return 0;
+
+err_swdev_register:
+	unregister_netdevice(dev);
+	return err;
+}
+
+static struct rtnl_link_ops dummysw_link_ops __read_mostly = {
+	.kind		= "dummysw",
+	.setup		= dummysw_setup,
+	.validate	= dummysw_validate,
+	.newlink	= dummysw_newlink,
+};
+
+
+/*
+ * Dummy switch port
+ */
+
+static void dummyswport_uninit(struct net_device *dev)
+{
+	__swportdev_unregister(dev);
+}
+
+static netdev_tx_t dummyswport_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops dummyswport_netdev_ops = {
+	.ndo_uninit		= dummyswport_uninit,
+	.ndo_start_xmit		= dummyswport_xmit,
+};
+
+static void dummyswport_setup(struct net_device *dev)
+{
+	ether_setup(dev);
+
+	/* Initialize the device structure. */
+	dev->netdev_ops = &dummyswport_netdev_ops;
+	dev->destructor = free_netdev;
+
+	/* Fill in device structure with ethernet-generic values. */
+	dev->tx_queue_len = 0;
+	dev->flags |= IFF_NOARP;
+	dev->flags &= ~IFF_MULTICAST;
+	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+	dev->features	|= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO;
+	dev->features	|= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
+}
+
+static int dummyswport_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+	if (tb[IFLA_ADDRESS])
+		return -EINVAL;
+	if (!data || !data[IFLA_DUMMYSWPORT_MASTER])
+		return -EINVAL;
+	return 0;
+}
+
+static int dummyswport_newlink(struct net *src_net, struct net_device *dev,
+			       struct nlattr *tb[], struct nlattr *data[])
+{
+	struct net_device *switch_dev;
+	uint32_t switch_ifindex;
+	int err;
+
+	switch_ifindex = nla_get_u32(data[IFLA_DUMMYSWPORT_MASTER]);
+	switch_dev = __dev_get_by_index(dev_net(dev), switch_ifindex);
+	if (!switch_dev)
+		return -ENODEV;
+	if (!swdev_dev_check(switch_dev))
+		return -EOPNOTSUPP;
+
+	err = register_netdevice(dev);
+	if (err)
+		return err;
+	err = __swportdev_register(dev, switch_dev);
+	if (err)
+		goto err_swportdev_register;
+
+	memcpy(dev->dev_addr, switch_dev->dev_addr, dev->addr_len);
+	dev->addr_assign_type = NET_ADDR_STOLEN;
+	netif_carrier_on(dev);
+
+	return 0;
+
+err_swportdev_register:
+	unregister_netdevice(dev);
+	return err;
+}
+
+static const struct nla_policy dummyswport_policy[IFLA_DUMMYSWPORT_MAX + 1] = {
+	[IFLA_DUMMYSWPORT_MASTER] = { .type = NLA_U32 },
+};
+
+static struct rtnl_link_ops dummyswport_link_ops __read_mostly = {
+	.kind		= "dummyswport",
+	.setup		= dummyswport_setup,
+	.validate	= dummyswport_validate,
+	.newlink	= dummyswport_newlink,
+	.policy		= dummyswport_policy,
+	.maxtype	= IFLA_DUMMYSWPORT_MAX,
+};
+
+
+/*
+ * Module init/exit
+ */
+
+static int __init dummysw_module_init(void)
+{
+	int err;
+
+	err = rtnl_link_register(&dummysw_link_ops);
+	if (err)
+		return err;
+	err = rtnl_link_register(&dummyswport_link_ops);
+	if (err)
+		goto err_rtnl_link_register;
+	return 0;
+
+err_rtnl_link_register:
+	rtnl_link_unregister(&dummysw_link_ops);
+	return err;
+}
+
+static void __exit dummysw_module_exit(void)
+{
+	rtnl_link_unregister(&dummyswport_link_ops);
+	rtnl_link_unregister(&dummysw_link_ops);
+}
+
+module_init(dummysw_module_init);
+module_exit(dummysw_module_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>");
+MODULE_DESCRIPTION("Dummy switch device");
+MODULE_ALIAS_RTNL_LINK("dummysw");
+MODULE_ALIAS_RTNL_LINK("dummyswport");
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 16410b6..ec14dd3 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -544,4 +544,13 @@ enum {
 
 #define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1)
 
+/* DUMMYSWPORT section */
+enum {
+	IFLA_DUMMYSWPORT_UNSPEC,
+	IFLA_DUMMYSWPORT_MASTER,
+	__IFLA_DUMMYSWPORT_MAX,
+};
+
+#define IFLA_DUMMYSWPORT_MAX (__IFLA_DUMMYSWPORT_MAX - 1)
+
 #endif /* _UAPI_LINUX_IF_LINK_H */
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [patch iproute2 RFC v2] iproute: add support for dummyswport
  2014-03-26 16:31 [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath Jiri Pirko
                   ` (3 preceding siblings ...)
  2014-03-26 16:31 ` [patch net-next RFC v2 4/6] net: introduce switchdev API Jiri Pirko
@ 2014-03-26 16:33 ` Jiri Pirko
       [not found] ` <1395851472-10524-1-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
  5 siblings, 0 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-26 16:33 UTC (permalink / raw
  To: netdev

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 include/linux/if_link.h |  9 +++++++++
 ip/Makefile             |  3 ++-
 ip/iplink_dummyswport.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 1 deletion(-)
 create mode 100644 ip/iplink_dummyswport.c

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index f08505c..aa3d619 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -542,4 +542,13 @@ enum {
 
 #define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1)
 
+/* DUMMYSWPORT section */
+enum {
+	IFLA_DUMMYSWPORT_UNSPEC,
+	IFLA_DUMMYSWPORT_MASTER,
+	__IFLA_DUMMYSWPORT_MAX,
+};
+
+#define IFLA_DUMMYSWPORT_MAX (__IFLA_DUMMYSWPORT_MAX - 1)
+
 #endif /* _LINUX_IF_LINK_H */
diff --git a/ip/Makefile b/ip/Makefile
index 713adf5..35546e5 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -5,7 +5,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
     iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
     iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
     iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
-    link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o
+    link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \
+    iplink_dummyswport.o \
 
 RTMONOBJ=rtmon.o
 
diff --git a/ip/iplink_dummyswport.c b/ip/iplink_dummyswport.c
new file mode 100644
index 0000000..a6476d1
--- /dev/null
+++ b/ip/iplink_dummyswport.c
@@ -0,0 +1,54 @@
+/*
+ * iplink_dummyswport.c		dummy switch port device support
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Authors:     Jiri Pirko <jiri@resnulli.us>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <linux/if_link.h>
+#include <net/if.h>
+
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+
+static void explain(void)
+{
+	fprintf(stderr, "Usage: ... dummyswport master DUMMYSW_DEV\n");
+}
+
+static int dummyswport_parse_opt(struct link_util *lu, int argc, char **argv,
+				 struct nlmsghdr *n)
+{
+	while (argc > 0) {
+		if (matches(*argv, "master") == 0) {
+			unsigned ifindex;
+
+			NEXT_ARG();
+			ifindex = if_nametoindex(*argv);
+			if (!ifindex)
+				invarg("Device does not exist\n", *argv);
+			addattr32(n, 1024, IFLA_DUMMYSWPORT_MASTER, ifindex);
+		} else {
+			fprintf(stderr, "dummyswport: unknown option \"%s\"?\n", *argv);
+			explain();
+			return -1;
+		}
+		argc--, argv++;
+	}
+	return 0;
+}
+
+struct link_util dummyswport_link_util = {
+	.id		= "dummyswport",
+	.maxattr	= IFLA_DUMMYSWPORT_MAX,
+	.parse_opt	= dummyswport_parse_opt,
+};
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 2/6] skbuff: add "missed_flow" flag
       [not found]   ` <1395851472-10524-3-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
@ 2014-03-26 16:59     ` Alexei Starovoitov
  2014-03-26 17:25       ` [ovs-dev] " Jiri Pirko
  2014-03-27 10:31     ` Nicolas Dichtel
  2014-03-31 20:39     ` Neil Jerram
  2 siblings, 1 reply; 31+ messages in thread
From: Alexei Starovoitov @ 2014-03-26 16:59 UTC (permalink / raw
  To: Jiri Pirko
  Cc: dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org,
	vyasevic-H+wXaHxf7aLQT0dZR+AlfA,
	f.fainelli-Re5JQEeQqe8AvxtiuMwx3w,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
	nhorman-2XuSBdqkA4R54TAoqtyWWQ,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	jhs-jkUAjuhPggJWk0Htik3J/w, linville-2XuSBdqkA4R54TAoqtyWWQ,
	john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w, Daniel Borkmann,
	Eric Dumazet, jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	Or Gerlitz, ben-/+tVBieCtBitmTQ+vhA3Yw, David S. Miller,
	andy-QlMahl40kYEqcZcGjlUOXw

On Wed, Mar 26, 2014 at 9:31 AM, Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org> wrote:
> This flag sets incoming switch device in order to let know that the flow
> which the skb is part of is missed. Listener may react to it
> appropriately,
>
> Signed-off-by: Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
> ---
>  include/linux/filter.h |  1 +
>  include/linux/skbuff.h | 13 +++++++++++++
>  net/core/filter.c      |  3 +++
>  3 files changed, 17 insertions(+)
>
> diff --git a/include/linux/filter.h b/include/linux/filter.h
> index e568c8e..38c7c04 100644
> --- a/include/linux/filter.h
> +++ b/include/linux/filter.h
> @@ -154,6 +154,7 @@ enum {
>         BPF_S_ANC_VLAN_TAG,
>         BPF_S_ANC_VLAN_TAG_PRESENT,
>         BPF_S_ANC_PAY_OFFSET,
> +       BPF_S_ANC_MISSED_FLOW,

Interesting use case for bpf...
looks like it's not connected to userspace.
Are you trying to extend ovs with switchdev api and bpf at once?
How do you plan to use this bpf extension?

Thanks
Alexei

>  };
>
>  #endif /* __LINUX_FILTER_H__ */
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 03db95a..0100c2f 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -567,6 +567,7 @@ struct sk_buff {
>          * headers if needed
>          */
>         __u8                    encapsulation:1;
> +       __u8                    missed_flow:1;
>         /* 6/8 bit hole (depending on ndisc_nodetype presence) */
>         kmemcheck_bitfield_end(flags2);
>
> @@ -2993,5 +2994,17 @@ static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
>                                skb_network_header(skb);
>         return hdr_len + skb_gso_transport_seglen(skb);
>  }
> +
> +/**
> + * skb_mark_missed_flow - marks skb as a part of missed flow
> + * @skb: buffer
> + *
> + * Marks skb as a part of missed flow.
> + */
> +static inline void skb_mark_missed_flow(struct sk_buff *skb)
> +{
> +       skb->missed_flow = 1;
> +}
> +
>  #endif /* __KERNEL__ */
>  #endif /* _LINUX_SKBUFF_H */
> diff --git a/net/core/filter.c b/net/core/filter.c
> index ad30d62..048f11a 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -350,6 +350,9 @@ load_b:
>                 case BPF_S_ANC_PAY_OFFSET:
>                         A = __skb_get_poff(skb);
>                         continue;
> +               case BPF_S_ANC_MISSED_FLOW:
> +                       A = !!skb->missed_flow;
> +                       continue;
>                 case BPF_S_ANC_NLATTR: {
>                         struct nlattr *nla;
>
> --
> 1.8.5.3
>
> _______________________________________________
> dev mailing list
> dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org
> http://openvswitch.org/mailman/listinfo/dev

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [ovs-dev] [patch net-next RFC v2 2/6] skbuff: add "missed_flow" flag
  2014-03-26 16:59     ` Alexei Starovoitov
@ 2014-03-26 17:25       ` Jiri Pirko
  0 siblings, 0 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-26 17:25 UTC (permalink / raw
  To: Alexei Starovoitov
  Cc: netdev@vger.kernel.org, john.r.fastabend, Eric Dumazet, andy,
	dev@openvswitch.org, f.fainelli, jeffrey.t.kirsher, Or Gerlitz,
	ben, roopa, jhs, linville, vyasevic, nhorman, sfeldma, stephen,
	Daniel Borkmann, David S. Miller

Wed, Mar 26, 2014 at 05:59:12PM CET, alexei.starovoitov@gmail.com wrote:
>On Wed, Mar 26, 2014 at 9:31 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>> This flag sets incoming switch device in order to let know that the flow
>> which the skb is part of is missed. Listener may react to it
>> appropriately,
>>
>> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
>> ---
>>  include/linux/filter.h |  1 +
>>  include/linux/skbuff.h | 13 +++++++++++++
>>  net/core/filter.c      |  3 +++
>>  3 files changed, 17 insertions(+)
>>
>> diff --git a/include/linux/filter.h b/include/linux/filter.h
>> index e568c8e..38c7c04 100644
>> --- a/include/linux/filter.h
>> +++ b/include/linux/filter.h
>> @@ -154,6 +154,7 @@ enum {
>>         BPF_S_ANC_VLAN_TAG,
>>         BPF_S_ANC_VLAN_TAG_PRESENT,
>>         BPF_S_ANC_PAY_OFFSET,
>> +       BPF_S_ANC_MISSED_FLOW,
>
>Interesting use case for bpf...
>looks like it's not connected to userspace.
>Are you trying to extend ovs with switchdev api and bpf at once?
>How do you plan to use this bpf extension?

The motive fot this is to provides a user (userspace app) possibility to
get all skbs which were "flow-missed". He can adjust the filter so that
only these can get through.



>
>Thanks
>Alexei
>
>>  };
>>
>>  #endif /* __LINUX_FILTER_H__ */
>> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
>> index 03db95a..0100c2f 100644
>> --- a/include/linux/skbuff.h
>> +++ b/include/linux/skbuff.h
>> @@ -567,6 +567,7 @@ struct sk_buff {
>>          * headers if needed
>>          */
>>         __u8                    encapsulation:1;
>> +       __u8                    missed_flow:1;
>>         /* 6/8 bit hole (depending on ndisc_nodetype presence) */
>>         kmemcheck_bitfield_end(flags2);
>>
>> @@ -2993,5 +2994,17 @@ static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
>>                                skb_network_header(skb);
>>         return hdr_len + skb_gso_transport_seglen(skb);
>>  }
>> +
>> +/**
>> + * skb_mark_missed_flow - marks skb as a part of missed flow
>> + * @skb: buffer
>> + *
>> + * Marks skb as a part of missed flow.
>> + */
>> +static inline void skb_mark_missed_flow(struct sk_buff *skb)
>> +{
>> +       skb->missed_flow = 1;
>> +}
>> +
>>  #endif /* __KERNEL__ */
>>  #endif /* _LINUX_SKBUFF_H */
>> diff --git a/net/core/filter.c b/net/core/filter.c
>> index ad30d62..048f11a 100644
>> --- a/net/core/filter.c
>> +++ b/net/core/filter.c
>> @@ -350,6 +350,9 @@ load_b:
>>                 case BPF_S_ANC_PAY_OFFSET:
>>                         A = __skb_get_poff(skb);
>>                         continue;
>> +               case BPF_S_ANC_MISSED_FLOW:
>> +                       A = !!skb->missed_flow;
>> +                       continue;
>>                 case BPF_S_ANC_NLATTR: {
>>                         struct nlattr *nla;
>>
>> --
>> 1.8.5.3
>>
>> _______________________________________________
>> dev mailing list
>> dev@openvswitch.org
>> http://openvswitch.org/mailman/listinfo/dev

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
       [not found] ` <1395851472-10524-1-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
  2014-03-26 16:31   ` [patch net-next RFC v2 5/6] openvswitch: Introduce support for switchdev based datapath Jiri Pirko
  2014-03-26 16:31   ` [patch net-next RFC v2 6/6] net: introduce dummy switch Jiri Pirko
@ 2014-03-26 21:44   ` Jamal Hadi Salim
       [not found]     ` <53334A3F.6020105-jkUAjuhPggJWk0Htik3J/w@public.gmane.org>
  2 siblings, 1 reply; 31+ messages in thread
From: Jamal Hadi Salim @ 2014-03-26 21:44 UTC (permalink / raw
  To: Jiri Pirko, netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: vyasevic-H+wXaHxf7aLQT0dZR+AlfA,
	john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w,
	f.fainelli-Re5JQEeQqe8AvxtiuMwx3w, nhorman-2XuSBdqkA4R54TAoqtyWWQ,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	linville-2XuSBdqkA4R54TAoqtyWWQ,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w, dev-yBygre7rU0TnMu66kgdUjQ,
	ben-/+tVBieCtBitmTQ+vhA3Yw, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	andy-QlMahl40kYEqcZcGjlUOXw

Jiri,

The flow extensions may be distracting - note there are many
tables (L3, L2, etc) in such chips not just ACLs. And there's likely no
OneWay(tm) to add a flow. My view is probably to solve or reach an
agreement on the ports. Then resolve the different tables control/data
exposure.
On the switchdev - You are still exposing it; do you expect these
things to be created from user space? Probably thats one approach, but
I would suspect the majority would result in the driver itself creating
these devices after discovering the resources from the control
interfaces (PCIE etc).

cheers,
jamal


On 03/26/14 12:31, Jiri Pirko wrote:
> This is second version of RFC. Here are the main differences from the first one:
> -There is no special swdev of swport structure. The switch and its ports are
>   now represented only by net_device structures. There are couple of switch-specific
>   ndos added (inserting and removing flows).
>
> -Regarding the flows, driver marks skb with "missing flow" flag now. That would
>   give indication to a user (OVS datapath of af_packet userspace application).
>   On the opposite direction, skb can be xmitted by a port.
>
> -dummyswitch module has now rtnetlink iface for easy creation of dummy switches
>   and ports.
>
> The basic idea is to introduce a generic infractructure to support various
> switch chips in kernel. Also the idea is to benefit of currently existing
> Open vSwitch userspace infrastructure.
>
>
> The first two patches are just minor skb flag and packet_type modifications.
>
>
> The third patch does a split of structures which are not specific to OVS
> into more generic ones that can be reused.
>
>
> The fourth patch introduces the "switchdev" API itself. It should serve as
> a glue between chip drivers on the one side and the user on the other.
> That user might be OVS datapath but in future it might be just userspace
> application interacting via af_packet and Netlink iface.
>
> The infrastructure is designed to be similar to for example linux bridge.
> There is one netdevice representing a switch chip and one netdevice per every
> port. These are bound together in classic slave-master way. The reason
> to reuse the netdevices for port representation is that userspace can use
> standard tools to get information about the ports, statistics, tcpdump, etc.
>
> Note that the netdevices are just representations of the ports in the switch.
> Therefore **no actual data** goes though, only missed flow skbs and, if drivers
> supports it, when ETH_P_ALL packet_type is hooked on (tcpdump).
>
>
> The fifth patch introduces a support for switchdev vports into OVS datapath.
> After that, userspace would be able to create a switchdev DP for a switch chip,
> to add switchdev ports to it and to use it in the same way as it would be
> OVS SW datapath.
>
>
> The sixth patch adds a dummy switch module. It is just an example of
> switchdev driver implementation.
>
>
> Jiri Pirko (6):
>    net: make packet_type->ak_packet_priv generic
>    skbuff: add "missed_flow" flag
>    openvswitch: split flow structures into ovs specific and generic ones
>    net: introduce switchdev API
>    openvswitch: Introduce support for switchdev based datapath
>    net: introduce dummy switch
>
>   drivers/net/Kconfig                        |   7 +
>   drivers/net/Makefile                       |   1 +
>   drivers/net/dummyswitch.c                  | 235 +++++++++++++++++++++++++++++
>   include/linux/filter.h                     |   1 +
>   include/linux/netdevice.h                  |  26 +++-
>   include/linux/skbuff.h                     |  13 ++
>   include/linux/sw_flow.h                    | 105 +++++++++++++
>   include/linux/switchdev.h                  |  30 ++++
>   include/uapi/linux/if_link.h               |   9 ++
>   include/uapi/linux/openvswitch.h           |   4 +
>   net/Kconfig                                |  10 ++
>   net/core/Makefile                          |   1 +
>   net/core/dev.c                             |   4 +-
>   net/core/filter.c                          |   3 +
>   net/core/switchdev.c                       | 172 +++++++++++++++++++++
>   net/openvswitch/Makefile                   |   4 +
>   net/openvswitch/datapath.c                 |  90 +++++++----
>   net/openvswitch/datapath.h                 |  12 +-
>   net/openvswitch/dp_notify.c                |   3 +-
>   net/openvswitch/flow.c                     |  14 +-
>   net/openvswitch/flow.h                     | 123 +++------------
>   net/openvswitch/flow_netlink.c             |  24 +--
>   net/openvswitch/flow_netlink.h             |   4 +-
>   net/openvswitch/flow_table.c               | 100 ++++++------
>   net/openvswitch/flow_table.h               |  18 +--
>   net/openvswitch/vport-gre.c                |   4 +-
>   net/openvswitch/vport-internal_switchdev.c | 179 ++++++++++++++++++++++
>   net/openvswitch/vport-internal_switchdev.h |  28 ++++
>   net/openvswitch/vport-netdev.c             |   4 +-
>   net/openvswitch/vport-switchportdev.c      | 205 +++++++++++++++++++++++++
>   net/openvswitch/vport-switchportdev.h      |  24 +++
>   net/openvswitch/vport-vxlan.c              |   2 +-
>   net/openvswitch/vport.c                    |   6 +-
>   net/openvswitch/vport.h                    |   4 +-
>   net/packet/af_packet.c                     |  22 ++-
>   35 files changed, 1269 insertions(+), 222 deletions(-)
>   create mode 100644 drivers/net/dummyswitch.c
>   create mode 100644 include/linux/sw_flow.h
>   create mode 100644 include/linux/switchdev.h
>   create mode 100644 net/core/switchdev.c
>   create mode 100644 net/openvswitch/vport-internal_switchdev.c
>   create mode 100644 net/openvswitch/vport-internal_switchdev.h
>   create mode 100644 net/openvswitch/vport-switchportdev.c
>   create mode 100644 net/openvswitch/vport-switchportdev.h
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
       [not found]     ` <53334A3F.6020105-jkUAjuhPggJWk0Htik3J/w@public.gmane.org>
@ 2014-03-26 21:57       ` Florian Fainelli
       [not found]         ` <CAGVrzcaOph7=2WfMzTfqtwFkN1fu5uKJAH59aF7mqD4MwL7iOg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2014-03-27  7:21       ` Jiri Pirko
  1 sibling, 1 reply; 31+ messages in thread
From: Florian Fainelli @ 2014-03-26 21:57 UTC (permalink / raw
  To: Jamal Hadi Salim
  Cc: John Fastabend, Eric Dumazet, Andy Gospodarek,
	dev-yBygre7rU0TnMu66kgdUjQ,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w, ogerlitz, Ben Hutchings,
	Jiri Pirko, Roopa Prabhu, John Linville, vyasevic, Neil Horman,
	Scott Feldman, netdev, Stephen Hemminger, dborkman, David Miller

2014-03-26 14:44 GMT-07:00 Jamal Hadi Salim <jhs-jkUAjuhPggJWk0Htik3J/w@public.gmane.org>:
> Jiri,
>
> The flow extensions may be distracting - note there are many
> tables (L3, L2, etc) in such chips not just ACLs. And there's likely no
> OneWay(tm) to add a flow. My view is probably to solve or reach an
> agreement on the ports. Then resolve the different tables control/data
> exposure.

Agreed.

> On the switchdev - You are still exposing it; do you expect these
> things to be created from user space? Probably thats one approach, but
> I would suspect the majority would result in the driver itself creating
> these devices after discovering the resources from the control
> interfaces (PCIE etc).

It seems to me like, minus the strong MDIO dependency, DSA is probably
the closest and most ready piece of software we have in the kernel to
start building Ethernet switch port net_device as it already contains
pretty much everything we want:

- per-port ethtool operations
- per-port xmit/rcv handlers
- existing drivers

The missing bits are roughly:

- adding IFF_SWITCH_PORT flags to the slave net_device created
- creating the switch master net_device: sw1
- creating the Switch CPU port net_device: sw1p<N>

>
> cheers,
> jamal
>
>
>
> On 03/26/14 12:31, Jiri Pirko wrote:
>>
>> This is second version of RFC. Here are the main differences from the
>> first one:
>> -There is no special swdev of swport structure. The switch and its ports
>> are
>>   now represented only by net_device structures. There are couple of
>> switch-specific
>>   ndos added (inserting and removing flows).
>>
>> -Regarding the flows, driver marks skb with "missing flow" flag now. That
>> would
>>   give indication to a user (OVS datapath of af_packet userspace
>> application).
>>   On the opposite direction, skb can be xmitted by a port.
>>
>> -dummyswitch module has now rtnetlink iface for easy creation of dummy
>> switches
>>   and ports.
>>
>> The basic idea is to introduce a generic infractructure to support various
>> switch chips in kernel. Also the idea is to benefit of currently existing
>> Open vSwitch userspace infrastructure.
>>
>>
>> The first two patches are just minor skb flag and packet_type
>> modifications.
>>
>>
>> The third patch does a split of structures which are not specific to OVS
>> into more generic ones that can be reused.
>>
>>
>> The fourth patch introduces the "switchdev" API itself. It should serve as
>> a glue between chip drivers on the one side and the user on the other.
>> That user might be OVS datapath but in future it might be just userspace
>> application interacting via af_packet and Netlink iface.
>>
>> The infrastructure is designed to be similar to for example linux bridge.
>> There is one netdevice representing a switch chip and one netdevice per
>> every
>> port. These are bound together in classic slave-master way. The reason
>> to reuse the netdevices for port representation is that userspace can use
>> standard tools to get information about the ports, statistics, tcpdump,
>> etc.
>>
>> Note that the netdevices are just representations of the ports in the
>> switch.
>> Therefore **no actual data** goes though, only missed flow skbs and, if
>> drivers
>> supports it, when ETH_P_ALL packet_type is hooked on (tcpdump).
>>
>>
>> The fifth patch introduces a support for switchdev vports into OVS
>> datapath.
>> After that, userspace would be able to create a switchdev DP for a switch
>> chip,
>> to add switchdev ports to it and to use it in the same way as it would be
>> OVS SW datapath.
>>
>>
>> The sixth patch adds a dummy switch module. It is just an example of
>> switchdev driver implementation.
>>
>>
>> Jiri Pirko (6):
>>    net: make packet_type->ak_packet_priv generic
>>    skbuff: add "missed_flow" flag
>>    openvswitch: split flow structures into ovs specific and generic ones
>>    net: introduce switchdev API
>>    openvswitch: Introduce support for switchdev based datapath
>>    net: introduce dummy switch
>>
>>   drivers/net/Kconfig                        |   7 +
>>   drivers/net/Makefile                       |   1 +
>>   drivers/net/dummyswitch.c                  | 235
>> +++++++++++++++++++++++++++++
>>   include/linux/filter.h                     |   1 +
>>   include/linux/netdevice.h                  |  26 +++-
>>   include/linux/skbuff.h                     |  13 ++
>>   include/linux/sw_flow.h                    | 105 +++++++++++++
>>   include/linux/switchdev.h                  |  30 ++++
>>   include/uapi/linux/if_link.h               |   9 ++
>>   include/uapi/linux/openvswitch.h           |   4 +
>>   net/Kconfig                                |  10 ++
>>   net/core/Makefile                          |   1 +
>>   net/core/dev.c                             |   4 +-
>>   net/core/filter.c                          |   3 +
>>   net/core/switchdev.c                       | 172 +++++++++++++++++++++
>>   net/openvswitch/Makefile                   |   4 +
>>   net/openvswitch/datapath.c                 |  90 +++++++----
>>   net/openvswitch/datapath.h                 |  12 +-
>>   net/openvswitch/dp_notify.c                |   3 +-
>>   net/openvswitch/flow.c                     |  14 +-
>>   net/openvswitch/flow.h                     | 123 +++------------
>>   net/openvswitch/flow_netlink.c             |  24 +--
>>   net/openvswitch/flow_netlink.h             |   4 +-
>>   net/openvswitch/flow_table.c               | 100 ++++++------
>>   net/openvswitch/flow_table.h               |  18 +--
>>   net/openvswitch/vport-gre.c                |   4 +-
>>   net/openvswitch/vport-internal_switchdev.c | 179 ++++++++++++++++++++++
>>   net/openvswitch/vport-internal_switchdev.h |  28 ++++
>>   net/openvswitch/vport-netdev.c             |   4 +-
>>   net/openvswitch/vport-switchportdev.c      | 205
>> +++++++++++++++++++++++++
>>   net/openvswitch/vport-switchportdev.h      |  24 +++
>>   net/openvswitch/vport-vxlan.c              |   2 +-
>>   net/openvswitch/vport.c                    |   6 +-
>>   net/openvswitch/vport.h                    |   4 +-
>>   net/packet/af_packet.c                     |  22 ++-
>>   35 files changed, 1269 insertions(+), 222 deletions(-)
>>   create mode 100644 drivers/net/dummyswitch.c
>>   create mode 100644 include/linux/sw_flow.h
>>   create mode 100644 include/linux/switchdev.h
>>   create mode 100644 net/core/switchdev.c
>>   create mode 100644 net/openvswitch/vport-internal_switchdev.c
>>   create mode 100644 net/openvswitch/vport-internal_switchdev.h
>>   create mode 100644 net/openvswitch/vport-switchportdev.c
>>   create mode 100644 net/openvswitch/vport-switchportdev.h
>>
>



-- 
Florian

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
       [not found]     ` <53334A3F.6020105-jkUAjuhPggJWk0Htik3J/w@public.gmane.org>
  2014-03-26 21:57       ` Florian Fainelli
@ 2014-03-27  7:21       ` Jiri Pirko
       [not found]         ` <20140327072107.GC2845-RDzucLLXGGI88b5SBfVpbw@public.gmane.org>
  1 sibling, 1 reply; 31+ messages in thread
From: Jiri Pirko @ 2014-03-27  7:21 UTC (permalink / raw
  To: Jamal Hadi Salim
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, andy-QlMahl40kYEqcZcGjlUOXw,
	dev-yBygre7rU0TnMu66kgdUjQ, f.fainelli-Re5JQEeQqe8AvxtiuMwx3w,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w, ben-/+tVBieCtBitmTQ+vhA3Yw,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	linville-2XuSBdqkA4R54TAoqtyWWQ, vyasevic-H+wXaHxf7aLQT0dZR+AlfA,
	nhorman-2XuSBdqkA4R54TAoqtyWWQ,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

Wed, Mar 26, 2014 at 10:44:31PM CET, jhs-jkUAjuhPggJWk0Htik3J/w@public.gmane.org wrote:
>Jiri,
>
>The flow extensions may be distracting - note there are many
>tables (L3, L2, etc) in such chips not just ACLs. And there's likely no
>OneWay(tm) to add a flow. My view is probably to solve or reach an
>agreement on the ports. Then resolve the different tables control/data
>exposure.

Well, I think there are 2 main models to be considered:
1. OSV-like model, where everything is flows and that is the OneWay(tm)
   mode you mentioned :)
2. clasic switch setting-like model where you manually set up vlans,
   lag, whatever.

The phase one for me is 1. and that is what I'm trying to resolve with
this patchset.

>From what I understand from the discussion, 2. is likely the model you
have in mind.



>On the switchdev - You are still exposing it; do you expect these
>things to be created from user space? Probably thats one approach, but
>I would suspect the majority would result in the driver itself creating
>these devices after discovering the resources from the control
>interfaces (PCIE etc).

Sorry, I'm not sure I follow you question correctly.
The driver should create and register the switch and switch ports itself.


>
>cheers,
>jamal
>
>
>On 03/26/14 12:31, Jiri Pirko wrote:
>>This is second version of RFC. Here are the main differences from the first one:
>>-There is no special swdev of swport structure. The switch and its ports are
>>  now represented only by net_device structures. There are couple of switch-specific
>>  ndos added (inserting and removing flows).
>>
>>-Regarding the flows, driver marks skb with "missing flow" flag now. That would
>>  give indication to a user (OVS datapath of af_packet userspace application).
>>  On the opposite direction, skb can be xmitted by a port.
>>
>>-dummyswitch module has now rtnetlink iface for easy creation of dummy switches
>>  and ports.
>>
>>The basic idea is to introduce a generic infractructure to support various
>>switch chips in kernel. Also the idea is to benefit of currently existing
>>Open vSwitch userspace infrastructure.
>>
>>
>>The first two patches are just minor skb flag and packet_type modifications.
>>
>>
>>The third patch does a split of structures which are not specific to OVS
>>into more generic ones that can be reused.
>>
>>
>>The fourth patch introduces the "switchdev" API itself. It should serve as
>>a glue between chip drivers on the one side and the user on the other.
>>That user might be OVS datapath but in future it might be just userspace
>>application interacting via af_packet and Netlink iface.
>>
>>The infrastructure is designed to be similar to for example linux bridge.
>>There is one netdevice representing a switch chip and one netdevice per every
>>port. These are bound together in classic slave-master way. The reason
>>to reuse the netdevices for port representation is that userspace can use
>>standard tools to get information about the ports, statistics, tcpdump, etc.
>>
>>Note that the netdevices are just representations of the ports in the switch.
>>Therefore **no actual data** goes though, only missed flow skbs and, if drivers
>>supports it, when ETH_P_ALL packet_type is hooked on (tcpdump).
>>
>>
>>The fifth patch introduces a support for switchdev vports into OVS datapath.
>>After that, userspace would be able to create a switchdev DP for a switch chip,
>>to add switchdev ports to it and to use it in the same way as it would be
>>OVS SW datapath.
>>
>>
>>The sixth patch adds a dummy switch module. It is just an example of
>>switchdev driver implementation.
>>
>>
>>Jiri Pirko (6):
>>   net: make packet_type->ak_packet_priv generic
>>   skbuff: add "missed_flow" flag
>>   openvswitch: split flow structures into ovs specific and generic ones
>>   net: introduce switchdev API
>>   openvswitch: Introduce support for switchdev based datapath
>>   net: introduce dummy switch
>>
>>  drivers/net/Kconfig                        |   7 +
>>  drivers/net/Makefile                       |   1 +
>>  drivers/net/dummyswitch.c                  | 235 +++++++++++++++++++++++++++++
>>  include/linux/filter.h                     |   1 +
>>  include/linux/netdevice.h                  |  26 +++-
>>  include/linux/skbuff.h                     |  13 ++
>>  include/linux/sw_flow.h                    | 105 +++++++++++++
>>  include/linux/switchdev.h                  |  30 ++++
>>  include/uapi/linux/if_link.h               |   9 ++
>>  include/uapi/linux/openvswitch.h           |   4 +
>>  net/Kconfig                                |  10 ++
>>  net/core/Makefile                          |   1 +
>>  net/core/dev.c                             |   4 +-
>>  net/core/filter.c                          |   3 +
>>  net/core/switchdev.c                       | 172 +++++++++++++++++++++
>>  net/openvswitch/Makefile                   |   4 +
>>  net/openvswitch/datapath.c                 |  90 +++++++----
>>  net/openvswitch/datapath.h                 |  12 +-
>>  net/openvswitch/dp_notify.c                |   3 +-
>>  net/openvswitch/flow.c                     |  14 +-
>>  net/openvswitch/flow.h                     | 123 +++------------
>>  net/openvswitch/flow_netlink.c             |  24 +--
>>  net/openvswitch/flow_netlink.h             |   4 +-
>>  net/openvswitch/flow_table.c               | 100 ++++++------
>>  net/openvswitch/flow_table.h               |  18 +--
>>  net/openvswitch/vport-gre.c                |   4 +-
>>  net/openvswitch/vport-internal_switchdev.c | 179 ++++++++++++++++++++++
>>  net/openvswitch/vport-internal_switchdev.h |  28 ++++
>>  net/openvswitch/vport-netdev.c             |   4 +-
>>  net/openvswitch/vport-switchportdev.c      | 205 +++++++++++++++++++++++++
>>  net/openvswitch/vport-switchportdev.h      |  24 +++
>>  net/openvswitch/vport-vxlan.c              |   2 +-
>>  net/openvswitch/vport.c                    |   6 +-
>>  net/openvswitch/vport.h                    |   4 +-
>>  net/packet/af_packet.c                     |  22 ++-
>>  35 files changed, 1269 insertions(+), 222 deletions(-)
>>  create mode 100644 drivers/net/dummyswitch.c
>>  create mode 100644 include/linux/sw_flow.h
>>  create mode 100644 include/linux/switchdev.h
>>  create mode 100644 net/core/switchdev.c
>>  create mode 100644 net/openvswitch/vport-internal_switchdev.c
>>  create mode 100644 net/openvswitch/vport-internal_switchdev.h
>>  create mode 100644 net/openvswitch/vport-switchportdev.c
>>  create mode 100644 net/openvswitch/vport-switchportdev.h
>>
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
       [not found]         ` <CAGVrzcaOph7=2WfMzTfqtwFkN1fu5uKJAH59aF7mqD4MwL7iOg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2014-03-27  7:23           ` Jiri Pirko
  0 siblings, 0 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-27  7:23 UTC (permalink / raw
  To: Florian Fainelli
  Cc: John Fastabend, Eric Dumazet, Andy Gospodarek,
	dev-yBygre7rU0TnMu66kgdUjQ,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w, ogerlitz, Ben Hutchings,
	Roopa Prabhu, Jamal Hadi Salim, John Linville, vyasevic,
	Neil Horman, Scott Feldman, netdev, Stephen Hemminger, dborkman,
	David Miller

Wed, Mar 26, 2014 at 10:57:09PM CET, f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
>2014-03-26 14:44 GMT-07:00 Jamal Hadi Salim <jhs-jkUAjuhPggJWk0Htik3J/w@public.gmane.org>:
>> Jiri,
>>
>> The flow extensions may be distracting - note there are many
>> tables (L3, L2, etc) in such chips not just ACLs. And there's likely no
>> OneWay(tm) to add a flow. My view is probably to solve or reach an
>> agreement on the ports. Then resolve the different tables control/data
>> exposure.
>
>Agreed.
>
>> On the switchdev - You are still exposing it; do you expect these
>> things to be created from user space? Probably thats one approach, but
>> I would suspect the majority would result in the driver itself creating
>> these devices after discovering the resources from the control
>> interfaces (PCIE etc).
>
>It seems to me like, minus the strong MDIO dependency, DSA is probably
>the closest and most ready piece of software we have in the kernel to
>start building Ethernet switch port net_device as it already contains
>pretty much everything we want:
>
>- per-port ethtool operations
>- per-port xmit/rcv handlers
>- existing drivers
>
>The missing bits are roughly:
>
>- adding IFF_SWITCH_PORT flags to the slave net_device created
>- creating the switch master net_device: sw1
>- creating the Switch CPU port net_device: sw1p<N>

Yep. DSA should be fairly easy to modify to use switchdev api.

>
>>
>> cheers,
>> jamal
>>
>>
>>
>> On 03/26/14 12:31, Jiri Pirko wrote:
>>>
>>> This is second version of RFC. Here are the main differences from the
>>> first one:
>>> -There is no special swdev of swport structure. The switch and its ports
>>> are
>>>   now represented only by net_device structures. There are couple of
>>> switch-specific
>>>   ndos added (inserting and removing flows).
>>>
>>> -Regarding the flows, driver marks skb with "missing flow" flag now. That
>>> would
>>>   give indication to a user (OVS datapath of af_packet userspace
>>> application).
>>>   On the opposite direction, skb can be xmitted by a port.
>>>
>>> -dummyswitch module has now rtnetlink iface for easy creation of dummy
>>> switches
>>>   and ports.
>>>
>>> The basic idea is to introduce a generic infractructure to support various
>>> switch chips in kernel. Also the idea is to benefit of currently existing
>>> Open vSwitch userspace infrastructure.
>>>
>>>
>>> The first two patches are just minor skb flag and packet_type
>>> modifications.
>>>
>>>
>>> The third patch does a split of structures which are not specific to OVS
>>> into more generic ones that can be reused.
>>>
>>>
>>> The fourth patch introduces the "switchdev" API itself. It should serve as
>>> a glue between chip drivers on the one side and the user on the other.
>>> That user might be OVS datapath but in future it might be just userspace
>>> application interacting via af_packet and Netlink iface.
>>>
>>> The infrastructure is designed to be similar to for example linux bridge.
>>> There is one netdevice representing a switch chip and one netdevice per
>>> every
>>> port. These are bound together in classic slave-master way. The reason
>>> to reuse the netdevices for port representation is that userspace can use
>>> standard tools to get information about the ports, statistics, tcpdump,
>>> etc.
>>>
>>> Note that the netdevices are just representations of the ports in the
>>> switch.
>>> Therefore **no actual data** goes though, only missed flow skbs and, if
>>> drivers
>>> supports it, when ETH_P_ALL packet_type is hooked on (tcpdump).
>>>
>>>
>>> The fifth patch introduces a support for switchdev vports into OVS
>>> datapath.
>>> After that, userspace would be able to create a switchdev DP for a switch
>>> chip,
>>> to add switchdev ports to it and to use it in the same way as it would be
>>> OVS SW datapath.
>>>
>>>
>>> The sixth patch adds a dummy switch module. It is just an example of
>>> switchdev driver implementation.
>>>
>>>
>>> Jiri Pirko (6):
>>>    net: make packet_type->ak_packet_priv generic
>>>    skbuff: add "missed_flow" flag
>>>    openvswitch: split flow structures into ovs specific and generic ones
>>>    net: introduce switchdev API
>>>    openvswitch: Introduce support for switchdev based datapath
>>>    net: introduce dummy switch
>>>
>>>   drivers/net/Kconfig                        |   7 +
>>>   drivers/net/Makefile                       |   1 +
>>>   drivers/net/dummyswitch.c                  | 235
>>> +++++++++++++++++++++++++++++
>>>   include/linux/filter.h                     |   1 +
>>>   include/linux/netdevice.h                  |  26 +++-
>>>   include/linux/skbuff.h                     |  13 ++
>>>   include/linux/sw_flow.h                    | 105 +++++++++++++
>>>   include/linux/switchdev.h                  |  30 ++++
>>>   include/uapi/linux/if_link.h               |   9 ++
>>>   include/uapi/linux/openvswitch.h           |   4 +
>>>   net/Kconfig                                |  10 ++
>>>   net/core/Makefile                          |   1 +
>>>   net/core/dev.c                             |   4 +-
>>>   net/core/filter.c                          |   3 +
>>>   net/core/switchdev.c                       | 172 +++++++++++++++++++++
>>>   net/openvswitch/Makefile                   |   4 +
>>>   net/openvswitch/datapath.c                 |  90 +++++++----
>>>   net/openvswitch/datapath.h                 |  12 +-
>>>   net/openvswitch/dp_notify.c                |   3 +-
>>>   net/openvswitch/flow.c                     |  14 +-
>>>   net/openvswitch/flow.h                     | 123 +++------------
>>>   net/openvswitch/flow_netlink.c             |  24 +--
>>>   net/openvswitch/flow_netlink.h             |   4 +-
>>>   net/openvswitch/flow_table.c               | 100 ++++++------
>>>   net/openvswitch/flow_table.h               |  18 +--
>>>   net/openvswitch/vport-gre.c                |   4 +-
>>>   net/openvswitch/vport-internal_switchdev.c | 179 ++++++++++++++++++++++
>>>   net/openvswitch/vport-internal_switchdev.h |  28 ++++
>>>   net/openvswitch/vport-netdev.c             |   4 +-
>>>   net/openvswitch/vport-switchportdev.c      | 205
>>> +++++++++++++++++++++++++
>>>   net/openvswitch/vport-switchportdev.h      |  24 +++
>>>   net/openvswitch/vport-vxlan.c              |   2 +-
>>>   net/openvswitch/vport.c                    |   6 +-
>>>   net/openvswitch/vport.h                    |   4 +-
>>>   net/packet/af_packet.c                     |  22 ++-
>>>   35 files changed, 1269 insertions(+), 222 deletions(-)
>>>   create mode 100644 drivers/net/dummyswitch.c
>>>   create mode 100644 include/linux/sw_flow.h
>>>   create mode 100644 include/linux/switchdev.h
>>>   create mode 100644 net/core/switchdev.c
>>>   create mode 100644 net/openvswitch/vport-internal_switchdev.c
>>>   create mode 100644 net/openvswitch/vport-internal_switchdev.h
>>>   create mode 100644 net/openvswitch/vport-switchportdev.c
>>>   create mode 100644 net/openvswitch/vport-switchportdev.h
>>>
>>
>
>
>
>-- 
>Florian

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
       [not found]         ` <20140327072107.GC2845-RDzucLLXGGI88b5SBfVpbw@public.gmane.org>
@ 2014-03-27 10:27           ` Jamal Hadi Salim
  2014-03-27 11:02             ` Thomas Graf
  0 siblings, 1 reply; 31+ messages in thread
From: Jamal Hadi Salim @ 2014-03-27 10:27 UTC (permalink / raw
  To: Jiri Pirko
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, andy-QlMahl40kYEqcZcGjlUOXw,
	dev-yBygre7rU0TnMu66kgdUjQ, f.fainelli-Re5JQEeQqe8AvxtiuMwx3w,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w, ben-/+tVBieCtBitmTQ+vhA3Yw,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	linville-2XuSBdqkA4R54TAoqtyWWQ, vyasevic-H+wXaHxf7aLQT0dZR+AlfA,
	nhorman-2XuSBdqkA4R54TAoqtyWWQ,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

On 03/27/14 03:21, Jiri Pirko wrote:
> Wed, Mar 26, 2014 at 10:44:31PM CET, jhs-jkUAjuhPggJWk0Htik3J/w@public.gmane.org wrote:

> Well, I think there are 2 main models to be considered:
> 1. OSV-like model, where everything is flows and that is the OneWay(tm)
>     mode you mentioned :)
> 2. clasic switch setting-like model where you manually set up vlans,
>     lag, whatever.
>
> The phase one for me is 1. and that is what I'm trying to resolve with
> this patchset.
>
>  From what I understand from the discussion, 2. is likely the model you
> have in mind.
>

In my opinion there is no difference when setting the ACL table(s).
We are going to need your .ndo for more than flows. Something
in the stack is going to have to talk to those .ndo interfaces
(I keep bringing up the concept of routing code for example).
What i meant by no OneWay is i think it will depend on the
chip - some will require more work than other. I do believe it
is a longer discussion needed than the port resolving.

cheers,
jamal

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 2/6] skbuff: add "missed_flow" flag
       [not found]   ` <1395851472-10524-3-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
  2014-03-26 16:59     ` Alexei Starovoitov
@ 2014-03-27 10:31     ` Nicolas Dichtel
       [not found]       ` <5333FE0E.2090008-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>
  2014-03-31 20:39     ` Neil Jerram
  2 siblings, 1 reply; 31+ messages in thread
From: Nicolas Dichtel @ 2014-03-27 10:31 UTC (permalink / raw
  To: Jiri Pirko, netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, andy-QlMahl40kYEqcZcGjlUOXw,
	dev-yBygre7rU0TnMu66kgdUjQ, f.fainelli-Re5JQEeQqe8AvxtiuMwx3w,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w, ben-/+tVBieCtBitmTQ+vhA3Yw,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	jhs-jkUAjuhPggJWk0Htik3J/w, linville-2XuSBdqkA4R54TAoqtyWWQ,
	vyasevic-H+wXaHxf7aLQT0dZR+AlfA, nhorman-2XuSBdqkA4R54TAoqtyWWQ,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

Le 26/03/2014 17:31, Jiri Pirko a écrit :
> This flag sets incoming switch device in order to let know that the flow
> which the skb is part of is missed. Listener may react to it
> appropriately,
>
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
> ---
>   include/linux/filter.h |  1 +
>   include/linux/skbuff.h | 13 +++++++++++++
>   net/core/filter.c      |  3 +++
>   3 files changed, 17 insertions(+)
>
> diff --git a/include/linux/filter.h b/include/linux/filter.h
> index e568c8e..38c7c04 100644
> --- a/include/linux/filter.h
> +++ b/include/linux/filter.h
> @@ -154,6 +154,7 @@ enum {
>   	BPF_S_ANC_VLAN_TAG,
>   	BPF_S_ANC_VLAN_TAG_PRESENT,
>   	BPF_S_ANC_PAY_OFFSET,
> +	BPF_S_ANC_MISSED_FLOW,
>   };
>
>   #endif /* __LINUX_FILTER_H__ */
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 03db95a..0100c2f 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -567,6 +567,7 @@ struct sk_buff {
>   	 * headers if needed
>   	 */
>   	__u8			encapsulation:1;
> +	__u8			missed_flow:1;
>   	/* 6/8 bit hole (depending on ndisc_nodetype presence) */
Please fix also the comment.
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 2/6] skbuff: add "missed_flow" flag
       [not found]       ` <5333FE0E.2090008-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>
@ 2014-03-27 10:34         ` Jiri Pirko
  0 siblings, 0 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-27 10:34 UTC (permalink / raw
  To: Nicolas Dichtel
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, andy-QlMahl40kYEqcZcGjlUOXw,
	dev-yBygre7rU0TnMu66kgdUjQ, f.fainelli-Re5JQEeQqe8AvxtiuMwx3w,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w, ben-/+tVBieCtBitmTQ+vhA3Yw,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	jhs-jkUAjuhPggJWk0Htik3J/w, linville-2XuSBdqkA4R54TAoqtyWWQ,
	vyasevic-H+wXaHxf7aLQT0dZR+AlfA, nhorman-2XuSBdqkA4R54TAoqtyWWQ,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

Thu, Mar 27, 2014 at 11:31:42AM CET, nicolas.dichtel-pdR9zngts4EAvxtiuMwx3w@public.gmane.org wrote:
>Le 26/03/2014 17:31, Jiri Pirko a écrit :
>>This flag sets incoming switch device in order to let know that the flow
>>which the skb is part of is missed. Listener may react to it
>>appropriately,
>>
>>Signed-off-by: Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
>>---
>>  include/linux/filter.h |  1 +
>>  include/linux/skbuff.h | 13 +++++++++++++
>>  net/core/filter.c      |  3 +++
>>  3 files changed, 17 insertions(+)
>>
>>diff --git a/include/linux/filter.h b/include/linux/filter.h
>>index e568c8e..38c7c04 100644
>>--- a/include/linux/filter.h
>>+++ b/include/linux/filter.h
>>@@ -154,6 +154,7 @@ enum {
>>  	BPF_S_ANC_VLAN_TAG,
>>  	BPF_S_ANC_VLAN_TAG_PRESENT,
>>  	BPF_S_ANC_PAY_OFFSET,
>>+	BPF_S_ANC_MISSED_FLOW,
>>  };
>>
>>  #endif /* __LINUX_FILTER_H__ */
>>diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
>>index 03db95a..0100c2f 100644
>>--- a/include/linux/skbuff.h
>>+++ b/include/linux/skbuff.h
>>@@ -567,6 +567,7 @@ struct sk_buff {
>>  	 * headers if needed
>>  	 */
>>  	__u8			encapsulation:1;
>>+	__u8			missed_flow:1;
>>  	/* 6/8 bit hole (depending on ndisc_nodetype presence) */
>Please fix also the comment.

will do. Thanks.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
  2014-03-27 10:27           ` Jamal Hadi Salim
@ 2014-03-27 11:02             ` Thomas Graf
  2014-03-27 11:17               ` Jamal Hadi Salim
  2014-03-27 16:27               ` Florian Fainelli
  0 siblings, 2 replies; 31+ messages in thread
From: Thomas Graf @ 2014-03-27 11:02 UTC (permalink / raw
  To: Jamal Hadi Salim
  Cc: Jiri Pirko, netdev, davem, nhorman, andy, dborkman, ogerlitz,
	jesse, pshelar, azhou, ben, stephen, jeffrey.t.kirsher, vyasevic,
	xiyou.wangcong, john.r.fastabend, edumazet, sfeldma, f.fainelli,
	roopa, linville, dev

On 03/27/14 at 06:27am, Jamal Hadi Salim wrote:
> On 03/27/14 03:21, Jiri Pirko wrote:
> >Wed, Mar 26, 2014 at 10:44:31PM CET, jhs@mojatatu.com wrote:
> 
> >Well, I think there are 2 main models to be considered:
> >1. OSV-like model, where everything is flows and that is the OneWay(tm)
> >    mode you mentioned :)
> >2. clasic switch setting-like model where you manually set up vlans,
> >    lag, whatever.
> >
> >The phase one for me is 1. and that is what I'm trying to resolve with
> >this patchset.
> >
> > From what I understand from the discussion, 2. is likely the model you
> >have in mind.
> >
> 
> In my opinion there is no difference when setting the ACL table(s).
> We are going to need your .ndo for more than flows. Something
> in the stack is going to have to talk to those .ndo interfaces
> (I keep bringing up the concept of routing code for example).
> What i meant by no OneWay is i think it will depend on the
> chip - some will require more work than other. I do believe it
> is a longer discussion needed than the port resolving.

There is definitely need beyond an ndo that is capable of
adding flows. You mention routes. Another example would be
devices capable of offloading iptables & nft rules.

But wouldn't you want to introduce an additional ndo to
cover these?

What speaks against going with what Jiri proposes and adjust
& extend as needed as we go along?

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
  2014-03-27 11:02             ` Thomas Graf
@ 2014-03-27 11:17               ` Jamal Hadi Salim
       [not found]                 ` <533408C0.8000608-jkUAjuhPggJWk0Htik3J/w@public.gmane.org>
  2014-03-27 16:27               ` Florian Fainelli
  1 sibling, 1 reply; 31+ messages in thread
From: Jamal Hadi Salim @ 2014-03-27 11:17 UTC (permalink / raw
  To: Thomas Graf
  Cc: Jiri Pirko, netdev, davem, nhorman, andy, dborkman, ogerlitz,
	jesse, pshelar, azhou, ben, stephen, jeffrey.t.kirsher, vyasevic,
	xiyou.wangcong, john.r.fastabend, edumazet, sfeldma, f.fainelli,
	roopa, linville, dev

On 03/27/14 07:02, Thomas Graf wrote:
> On 03/27/14 at 06:27am, Jamal Hadi Salim wrote:

> There is definitely need beyond an ndo that is capable of
> adding flows. You mention routes. Another example would be
> devices capable of offloading iptables & nft rules.
>

nod.

> But wouldn't you want to introduce an additional ndo to
> cover these?

We could - I just find it distracting at the current thread
of discussion (the openwrt folks for example dont need any
or most of that).

> What speaks against going with what Jiri proposes and adjust
> & extend as needed as we go along?
>

I was hoping we knock these issue one at a time. The noise right
now is around ports and stacking of ports etc. Which in my
opinion is an easier topic to handle.
Jiri's patches on this can always come back in the discussion
later.

cheers,
jamal

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 4/6] net: introduce switchdev API
  2014-03-26 16:31 ` [patch net-next RFC v2 4/6] net: introduce switchdev API Jiri Pirko
@ 2014-03-27 11:23   ` Thomas Graf
       [not found]     ` <20140327112339.GB1615-FZi0V3Vbi30CUdFEqe4BF2D2FQJk+8+b@public.gmane.org>
       [not found]   ` <1395851472-10524-5-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
  1 sibling, 1 reply; 31+ messages in thread
From: Thomas Graf @ 2014-03-27 11:23 UTC (permalink / raw
  To: Jiri Pirko
  Cc: netdev, davem, nhorman, andy, dborkman, ogerlitz, jesse, pshelar,
	azhou, ben, stephen, jeffrey.t.kirsher, vyasevic, xiyou.wangcong,
	john.r.fastabend, edumazet, jhs, sfeldma, f.fainelli, roopa,
	linville, dev

On 03/26/14 at 05:31pm, Jiri Pirko wrote:
> switchdev API is designed to allow kernel support for various switch
> chips.
> 
> It is the responsibility of a driver to create netdevice instances which
> represents every port and for the switch master itself. Driver uses
> swdev_register and swportdev_register functions to make the core aware
> of the fact these netdevices are representing switch and switch ports.

I like this even more than the previous approach.

> 
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>

> +int __swdev_register(struct net_device *dev)
> +{
> +	if (dev->priv_flags & IFF_SWITCH) {
> +		netdev_err(dev, "Device is already registered as a switch device\n");
> +		return -EBUSY;
> +	}
> +	dev->priv_flags |= IFF_SWITCH;
> +	netdev_info(dev, "Switch device registered\n");

Perhaps include name of device here?

> +	return 0;
> +}
> +EXPORT_SYMBOL(__swdev_register);
> +
> +int swdev_register(struct net_device *dev)
> +{
> +	int err;
> +
> +	rtnl_lock();
> +	err = __swdev_register(dev);
> +	rtnl_unlock();
> +	return err;
> +}
> +EXPORT_SYMBOL(swdev_register);
> +
> +void __swdev_unregister(struct net_device *dev)
> +{
> +	dev->priv_flags |= IFF_SWITCH;
> +	netdev_info(dev, "Switch device unregistered\n");

Same here

> +}
> +EXPORT_SYMBOL(__swdev_unregister);
> +
> +void swdev_unregister(struct net_device *dev)
> +{
> +	rtnl_lock();
> +	__swdev_unregister(dev);
> +	rtnl_unlock();
> +}
> +EXPORT_SYMBOL(swdev_unregister);
> +
> +
> +bool swportdev_dev_check(const struct net_device *port_dev)
> +{
> +	return port_dev->priv_flags & IFF_SWITCH_PORT;
> +}
> +EXPORT_SYMBOL(swportdev_dev_check);
> +
> +static rx_handler_result_t swportdev_handle_frame(struct sk_buff **pskb)
> +{
> +	struct sk_buff *skb = *pskb;
> +
> +	/* We don't care what comes from port device into rx path.
> +	 * If there's something there, it is destined to ETH_P_ALL
> +	 * handlers. So just consume it.
> +	 */
> +	dev_kfree_skb(skb);
> +	return RX_HANDLER_CONSUMED;
> +}
> +
> +int __swportdev_register(struct net_device *port_dev, struct net_device *dev)
> +{
> +	int err;
> +
> +	if (!(dev->priv_flags & IFF_SWITCH)) {
> +		netdev_err(dev, "Device is not a switch device\n");
> +		return -EINVAL;
> +	}
> +	if (port_dev->priv_flags & IFF_SWITCH_PORT) {
> +		netdev_err(port_dev, "Device is already registered as a switch port\n");
> +		return -EBUSY;
> +	}
> +	err = netdev_master_upper_dev_link(port_dev, dev);
> +	if (err) {
> +		netdev_err(dev, "Device %s failed to set upper link\n",
> +			   port_dev->name);
> +		return err;
> +	}
> +	err = netdev_rx_handler_register(port_dev, swportdev_handle_frame, NULL);
> +	if (err) {
> +		netdev_err(dev, "Device %s failed to register rx_handler\n",
> +			   port_dev->name);
> +		goto err_handler_register;
> +	}
> +	port_dev->priv_flags |= IFF_SWITCH_PORT;
> +	netdev_info(port_dev, "Switch port device registered\n");

and here

> +	return 0;
> +
> +err_handler_register:
> +	netdev_upper_dev_unlink(port_dev, dev);
> +	return err;
> +}
> +EXPORT_SYMBOL(__swportdev_register);
> +
> +int swportdev_register(struct net_device *port_dev, struct net_device *dev)

Maybe rename dev to switch_dev just to make it clear?

> +{
> +	int err;
> +
> +	rtnl_lock();
> +	err = __swportdev_register(port_dev, dev);
> +	rtnl_unlock();
> +	return err;
> +}
> +EXPORT_SYMBOL(swportdev_register);
> +
> +void __swportdev_unregister(struct net_device *port_dev)
> +{
> +	struct net_device *dev;
> +
> +	dev = netdev_master_upper_dev_get(port_dev);
> +	BUG_ON(!dev);
> +	port_dev->priv_flags &= ~IFF_SWITCH_PORT;
> +	netdev_rx_handler_unregister(port_dev);
> +	netdev_upper_dev_unlink(port_dev, dev);
> +	netdev_info(port_dev, "Switch port device unregistered\n");
> +}
> +EXPORT_SYMBOL(__swportdev_unregister);
> +
> +void swportdev_unregister(struct net_device *port_dev)
> +{
> +	rtnl_lock();
> +	__swportdev_unregister(port_dev);
> +	rtnl_unlock();
> +}
> +EXPORT_SYMBOL(swportdev_unregister);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Jiri Pirko <jiri@resnulli.us>");
> +MODULE_DESCRIPTION("Switch device API");
> -- 
> 1.8.5.3
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 4/6] net: introduce switchdev API
       [not found]     ` <20140327112339.GB1615-FZi0V3Vbi30CUdFEqe4BF2D2FQJk+8+b@public.gmane.org>
@ 2014-03-27 11:26       ` Jiri Pirko
  0 siblings, 0 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-27 11:26 UTC (permalink / raw
  To: Thomas Graf
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, andy-QlMahl40kYEqcZcGjlUOXw,
	dev-yBygre7rU0TnMu66kgdUjQ, f.fainelli-Re5JQEeQqe8AvxtiuMwx3w,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w, ben-/+tVBieCtBitmTQ+vhA3Yw,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	jhs-jkUAjuhPggJWk0Htik3J/w, linville-2XuSBdqkA4R54TAoqtyWWQ,
	vyasevic-H+wXaHxf7aLQT0dZR+AlfA, nhorman-2XuSBdqkA4R54TAoqtyWWQ,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

Thu, Mar 27, 2014 at 12:23:39PM CET, tgraf-G/eBtMaohhA@public.gmane.org wrote:
>On 03/26/14 at 05:31pm, Jiri Pirko wrote:
>> switchdev API is designed to allow kernel support for various switch
>> chips.
>> 
>> It is the responsibility of a driver to create netdevice instances which
>> represents every port and for the switch master itself. Driver uses
>> swdev_register and swportdev_register functions to make the core aware
>> of the fact these netdevices are representing switch and switch ports.
>
>I like this even more than the previous approach.
>
>> 
>> Signed-off-by: Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
>
>> +int __swdev_register(struct net_device *dev)
>> +{
>> +	if (dev->priv_flags & IFF_SWITCH) {
>> +		netdev_err(dev, "Device is already registered as a switch device\n");
>> +		return -EBUSY;
>> +	}
>> +	dev->priv_flags |= IFF_SWITCH;
>> +	netdev_info(dev, "Switch device registered\n");
>
>Perhaps include name of device here?

netdev_info already does that.


>
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL(__swdev_register);
>> +
>> +int swdev_register(struct net_device *dev)
>> +{
>> +	int err;
>> +
>> +	rtnl_lock();
>> +	err = __swdev_register(dev);
>> +	rtnl_unlock();
>> +	return err;
>> +}
>> +EXPORT_SYMBOL(swdev_register);
>> +
>> +void __swdev_unregister(struct net_device *dev)
>> +{
>> +	dev->priv_flags |= IFF_SWITCH;
>> +	netdev_info(dev, "Switch device unregistered\n");
>
>Same here
>
>> +}
>> +EXPORT_SYMBOL(__swdev_unregister);
>> +
>> +void swdev_unregister(struct net_device *dev)
>> +{
>> +	rtnl_lock();
>> +	__swdev_unregister(dev);
>> +	rtnl_unlock();
>> +}
>> +EXPORT_SYMBOL(swdev_unregister);
>> +
>> +
>> +bool swportdev_dev_check(const struct net_device *port_dev)
>> +{
>> +	return port_dev->priv_flags & IFF_SWITCH_PORT;
>> +}
>> +EXPORT_SYMBOL(swportdev_dev_check);
>> +
>> +static rx_handler_result_t swportdev_handle_frame(struct sk_buff **pskb)
>> +{
>> +	struct sk_buff *skb = *pskb;
>> +
>> +	/* We don't care what comes from port device into rx path.
>> +	 * If there's something there, it is destined to ETH_P_ALL
>> +	 * handlers. So just consume it.
>> +	 */
>> +	dev_kfree_skb(skb);
>> +	return RX_HANDLER_CONSUMED;
>> +}
>> +
>> +int __swportdev_register(struct net_device *port_dev, struct net_device *dev)
>> +{
>> +	int err;
>> +
>> +	if (!(dev->priv_flags & IFF_SWITCH)) {
>> +		netdev_err(dev, "Device is not a switch device\n");
>> +		return -EINVAL;
>> +	}
>> +	if (port_dev->priv_flags & IFF_SWITCH_PORT) {
>> +		netdev_err(port_dev, "Device is already registered as a switch port\n");
>> +		return -EBUSY;
>> +	}
>> +	err = netdev_master_upper_dev_link(port_dev, dev);
>> +	if (err) {
>> +		netdev_err(dev, "Device %s failed to set upper link\n",
>> +			   port_dev->name);
>> +		return err;
>> +	}
>> +	err = netdev_rx_handler_register(port_dev, swportdev_handle_frame, NULL);
>> +	if (err) {
>> +		netdev_err(dev, "Device %s failed to register rx_handler\n",
>> +			   port_dev->name);
>> +		goto err_handler_register;
>> +	}
>> +	port_dev->priv_flags |= IFF_SWITCH_PORT;
>> +	netdev_info(port_dev, "Switch port device registered\n");
>
>and here
>
>> +	return 0;
>> +
>> +err_handler_register:
>> +	netdev_upper_dev_unlink(port_dev, dev);
>> +	return err;
>> +}
>> +EXPORT_SYMBOL(__swportdev_register);
>> +
>> +int swportdev_register(struct net_device *port_dev, struct net_device *dev)
>
>Maybe rename dev to switch_dev just to make it clear?


That might be reasonable.


>
>> +{
>> +	int err;
>> +
>> +	rtnl_lock();
>> +	err = __swportdev_register(port_dev, dev);
>> +	rtnl_unlock();
>> +	return err;
>> +}
>> +EXPORT_SYMBOL(swportdev_register);
>> +
>> +void __swportdev_unregister(struct net_device *port_dev)
>> +{
>> +	struct net_device *dev;
>> +
>> +	dev = netdev_master_upper_dev_get(port_dev);
>> +	BUG_ON(!dev);
>> +	port_dev->priv_flags &= ~IFF_SWITCH_PORT;
>> +	netdev_rx_handler_unregister(port_dev);
>> +	netdev_upper_dev_unlink(port_dev, dev);
>> +	netdev_info(port_dev, "Switch port device unregistered\n");
>> +}
>> +EXPORT_SYMBOL(__swportdev_unregister);
>> +
>> +void swportdev_unregister(struct net_device *port_dev)
>> +{
>> +	rtnl_lock();
>> +	__swportdev_unregister(port_dev);
>> +	rtnl_unlock();
>> +}
>> +EXPORT_SYMBOL(swportdev_unregister);
>> +
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_AUTHOR("Jiri Pirko <jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>");
>> +MODULE_DESCRIPTION("Switch device API");
>> -- 
>> 1.8.5.3
>> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
       [not found]                 ` <533408C0.8000608-jkUAjuhPggJWk0Htik3J/w@public.gmane.org>
@ 2014-03-27 12:00                   ` Thomas Graf
  2014-03-27 12:32                     ` Jamal Hadi Salim
  0 siblings, 1 reply; 31+ messages in thread
From: Thomas Graf @ 2014-03-27 12:00 UTC (permalink / raw
  To: Jamal Hadi Salim
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, andy-QlMahl40kYEqcZcGjlUOXw,
	dev-yBygre7rU0TnMu66kgdUjQ, f.fainelli-Re5JQEeQqe8AvxtiuMwx3w,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w, ben-/+tVBieCtBitmTQ+vhA3Yw,
	Jiri Pirko, roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	linville-2XuSBdqkA4R54TAoqtyWWQ, vyasevic-H+wXaHxf7aLQT0dZR+AlfA,
	nhorman-2XuSBdqkA4R54TAoqtyWWQ,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

On 03/27/14 at 07:17am, Jamal Hadi Salim wrote:
> On 03/27/14 07:02, Thomas Graf wrote:
> >But wouldn't you want to introduce an additional ndo to
> >cover these?
> 
> We could - I just find it distracting at the current thread
> of discussion (the openwrt folks for example dont need any
> or most of that).
> 
> >What speaks against going with what Jiri proposes and adjust
> >& extend as needed as we go along?
> >
> 
> I was hoping we knock these issue one at a time. The noise right
> now is around ports and stacking of ports etc. Which in my
> opinion is an easier topic to handle.
> Jiri's patches on this can always come back in the discussion
> later.

It seems like we reached pretty good consensus on the model. What
remaining issues do you see with the port model proposed in v2?

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
  2014-03-27 12:00                   ` Thomas Graf
@ 2014-03-27 12:32                     ` Jamal Hadi Salim
  2014-03-27 12:57                       ` Jiri Pirko
  0 siblings, 1 reply; 31+ messages in thread
From: Jamal Hadi Salim @ 2014-03-27 12:32 UTC (permalink / raw
  To: Thomas Graf
  Cc: Jiri Pirko, netdev, davem, nhorman, andy, dborkman, ogerlitz,
	jesse, pshelar, azhou, ben, stephen, jeffrey.t.kirsher, vyasevic,
	xiyou.wangcong, john.r.fastabend, edumazet, sfeldma, f.fainelli,
	roopa, linville, dev

On 03/27/14 08:00, Thomas Graf wrote:

> It seems like we reached pretty good consensus on the model. What
> remaining issues do you see with the port model proposed in v2?
>

Are we really following the same thread?
I dont see any rallying behind Jiri's approach from the
other folks who have their own code and way of approaching things.
I am hoping we dont continue with the split that is there
already.

cheers,
jamal

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
  2014-03-27 12:32                     ` Jamal Hadi Salim
@ 2014-03-27 12:57                       ` Jiri Pirko
       [not found]                         ` <20140327125711.GL2845-RDzucLLXGGI88b5SBfVpbw@public.gmane.org>
  0 siblings, 1 reply; 31+ messages in thread
From: Jiri Pirko @ 2014-03-27 12:57 UTC (permalink / raw
  To: Jamal Hadi Salim
  Cc: Thomas Graf, netdev, davem, nhorman, andy, dborkman, ogerlitz,
	jesse, pshelar, azhou, ben, stephen, jeffrey.t.kirsher, vyasevic,
	xiyou.wangcong, john.r.fastabend, edumazet, sfeldma, f.fainelli,
	roopa, linville, dev

Thu, Mar 27, 2014 at 01:32:35PM CET, jhs@mojatatu.com wrote:
>On 03/27/14 08:00, Thomas Graf wrote:
>
>>It seems like we reached pretty good consensus on the model. What
>>remaining issues do you see with the port model proposed in v2?
>>
>
>Are we really following the same thread?
>I dont see any rallying behind Jiri's approach from the
>other folks who have their own code and way of approaching things.
>I am hoping we dont continue with the split that is there
>already.

It is not a split. It is just a completion of a model. Adding missing
parts. At least I see it that way.

>
>cheers,
>jamal

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
       [not found]                         ` <20140327125711.GL2845-RDzucLLXGGI88b5SBfVpbw@public.gmane.org>
@ 2014-03-27 14:03                           ` John W. Linville
  0 siblings, 0 replies; 31+ messages in thread
From: John W. Linville @ 2014-03-27 14:03 UTC (permalink / raw
  To: Jiri Pirko
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA, andy-QlMahl40kYEqcZcGjlUOXw,
	dev-yBygre7rU0TnMu66kgdUjQ, f.fainelli-Re5JQEeQqe8AvxtiuMwx3w,
	jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	ogerlitz-VPRAkNaXOzVWk0Htik3J/w, ben-/+tVBieCtBitmTQ+vhA3Yw,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR, Jamal Hadi Salim,
	vyasevic-H+wXaHxf7aLQT0dZR+AlfA, nhorman-2XuSBdqkA4R54TAoqtyWWQ,
	sfeldma-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	stephen-OTpzqLSitTUnbdJkjeBofR2eb7JE58TQ,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA, davem-fT/PcQaiUtIeIZ0/mPfg9Q

On Thu, Mar 27, 2014 at 01:57:11PM +0100, Jiri Pirko wrote:
> Thu, Mar 27, 2014 at 01:32:35PM CET, jhs-jkUAjuhPggJWk0Htik3J/w@public.gmane.org wrote:
> >On 03/27/14 08:00, Thomas Graf wrote:
> >
> >>It seems like we reached pretty good consensus on the model. What
> >>remaining issues do you see with the port model proposed in v2?
> >>
> >
> >Are we really following the same thread?
> >I dont see any rallying behind Jiri's approach from the
> >other folks who have their own code and way of approaching things.
> >I am hoping we dont continue with the split that is there
> >already.
> 
> It is not a split. It is just a completion of a model. Adding missing
> parts. At least I see it that way.

I probably wouldn't call it a 'split' either.  But, I agree with
Jamal that we are nowhere near consensus so far.

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org			might be all we have.  Be ready.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
  2014-03-27 11:02             ` Thomas Graf
  2014-03-27 11:17               ` Jamal Hadi Salim
@ 2014-03-27 16:27               ` Florian Fainelli
  2014-03-27 17:20                 ` Thomas Graf
  1 sibling, 1 reply; 31+ messages in thread
From: Florian Fainelli @ 2014-03-27 16:27 UTC (permalink / raw
  To: Thomas Graf
  Cc: Jamal Hadi Salim, Jiri Pirko, netdev, David Miller, Neil Horman,
	Andy Gospodarek, dborkman, ogerlitz, jesse, pshelar, azhou,
	Ben Hutchings, Stephen Hemminger, jeffrey.t.kirsher, vyasevic,
	Cong Wang, John Fastabend, Eric Dumazet, Scott Feldman,
	Roopa Prabhu, John Linville, dev

2014-03-27 4:02 GMT-07:00 Thomas Graf <tgraf@suug.ch>:
> On 03/27/14 at 06:27am, Jamal Hadi Salim wrote:
>> On 03/27/14 03:21, Jiri Pirko wrote:
>> >Wed, Mar 26, 2014 at 10:44:31PM CET, jhs@mojatatu.com wrote:
>>
>> >Well, I think there are 2 main models to be considered:
>> >1. OSV-like model, where everything is flows and that is the OneWay(tm)
>> >    mode you mentioned :)
>> >2. clasic switch setting-like model where you manually set up vlans,
>> >    lag, whatever.
>> >
>> >The phase one for me is 1. and that is what I'm trying to resolve with
>> >this patchset.
>> >
>> > From what I understand from the discussion, 2. is likely the model you
>> >have in mind.
>> >
>>
>> In my opinion there is no difference when setting the ACL table(s).
>> We are going to need your .ndo for more than flows. Something
>> in the stack is going to have to talk to those .ndo interfaces
>> (I keep bringing up the concept of routing code for example).
>> What i meant by no OneWay is i think it will depend on the
>> chip - some will require more work than other. I do believe it
>> is a longer discussion needed than the port resolving.
>
> There is definitely need beyond an ndo that is capable of
> adding flows. You mention routes. Another example would be
> devices capable of offloading iptables & nft rules.

Those devices usually require (at least for Broadcom) an entity
identifying the flows and uploading flows offloading rules to the
hardware. Although I do not think it hurts to keep those in mind to
come up with the right design, my feeling is that they will require
more intrusive modifications at the socket, route and forwarding path
level if we want the Linux kernel to offer a consistent API across
different hardware variations.

It is not clear to me at this point whether we want those special
offloading devices to appear as separate net_device with specific
flags to advertise their offloading features (NAT, IP routing...) or
something else?

>
> But wouldn't you want to introduce an additional ndo to
> cover these?

I would start with making sure everyone is on the same page regarding
switches before we start building the conversation on NAT/IP-routing
offloading, but it is good that you mention it.

>
> What speaks against going with what Jiri proposes and adjust
> & extend as needed as we go along?


-- 
Florian

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
  2014-03-27 16:27               ` Florian Fainelli
@ 2014-03-27 17:20                 ` Thomas Graf
       [not found]                   ` <20140327172048.GC13573-FZi0V3Vbi30CUdFEqe4BF2D2FQJk+8+b@public.gmane.org>
  0 siblings, 1 reply; 31+ messages in thread
From: Thomas Graf @ 2014-03-27 17:20 UTC (permalink / raw
  To: Florian Fainelli
  Cc: Jamal Hadi Salim, Jiri Pirko, netdev, David Miller, Neil Horman,
	Andy Gospodarek, dborkman, ogerlitz, jesse, pshelar, azhou,
	Ben Hutchings, Stephen Hemminger, jeffrey.t.kirsher, vyasevic,
	Cong Wang, John Fastabend, Eric Dumazet, Scott Feldman,
	Roopa Prabhu, John Linville, dev

On 03/27/14 at 09:27am, Florian Fainelli wrote:
> 2014-03-27 4:02 GMT-07:00 Thomas Graf <tgraf@suug.ch>:
> > There is definitely need beyond an ndo that is capable of
> > adding flows. You mention routes. Another example would be
> > devices capable of offloading iptables & nft rules.
> 
> Those devices usually require (at least for Broadcom) an entity
> identifying the flows and uploading flows offloading rules to the
> hardware. Although I do not think it hurts to keep those in mind to
> come up with the right design, my feeling is that they will require
> more intrusive modifications at the socket, route and forwarding path
> level if we want the Linux kernel to offer a consistent API across
> different hardware variations.

I absolutely agree. This is where the challenging bits start to
appear ;-) I don't want to speak for Jiri but my understanding is
that the flow focused approach early on is entirely because it is
the easiest case to solve. Taking OVS as an example has the
advantage of already being guarded by OpenFlow abstraction which
by nature is very device oriented.

> It is not clear to me at this point whether we want those special
> offloading devices to appear as separate net_device with specific
> flags to advertise their offloading features (NAT, IP routing...) or
> something else?

One lesson that could serve as an example which differs from TOE is
the offloading provided by recent FC HBAs. The device looks like a
regular SCSI device to the kernel but offers a full DCB engine to
allow for FCoE. The DCB bits can and must be configured. By not
representing that engine with a net_device we cannot configure the
engine through the Netlink interface dcbnl. dcbnl can certainly be
extended to allow taking a scsi id of some sort instead of a ifindex
but it's far from ideal.

My take on this is that if it makes sense to use rtnl or ethtool
to configure these offload engines then let's just go with a
globally visible net_device and improve our capabilities system.

> > But wouldn't you want to introduce an additional ndo to
> > cover these?
> 
> I would start with making sure everyone is on the same page regarding
> switches before we start building the conversation on NAT/IP-routing
> offloading, but it is good that you mention it.

Agreed

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath
       [not found]                   ` <20140327172048.GC13573-FZi0V3Vbi30CUdFEqe4BF2D2FQJk+8+b@public.gmane.org>
@ 2014-03-27 17:26                     ` Jiri Pirko
  0 siblings, 0 replies; 31+ messages in thread
From: Jiri Pirko @ 2014-03-27 17:26 UTC (permalink / raw
  To: Thomas Graf
  Cc: John Fastabend, Eric Dumazet, Andy Gospodarek, dev,
	Florian Fainelli, jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w,
	ogerlitz, Ben Hutchings, Roopa Prabhu, Jamal Hadi Salim,
	John Linville, vyasevic, Neil Horman, Scott Feldman, netdev,
	Stephen Hemminger, dborkman, David Miller

Thu, Mar 27, 2014 at 06:20:48PM CET, tgraf-G/eBtMaohhA@public.gmane.org wrote:
>On 03/27/14 at 09:27am, Florian Fainelli wrote:
>> 2014-03-27 4:02 GMT-07:00 Thomas Graf <tgraf-G/eBtMaohhA@public.gmane.org>:
>> > There is definitely need beyond an ndo that is capable of
>> > adding flows. You mention routes. Another example would be
>> > devices capable of offloading iptables & nft rules.
>> 
>> Those devices usually require (at least for Broadcom) an entity
>> identifying the flows and uploading flows offloading rules to the
>> hardware. Although I do not think it hurts to keep those in mind to
>> come up with the right design, my feeling is that they will require
>> more intrusive modifications at the socket, route and forwarding path
>> level if we want the Linux kernel to offer a consistent API across
>> different hardware variations.
>
>I absolutely agree. This is where the challenging bits start to
>appear ;-) I don't want to speak for Jiri but my understanding is
>that the flow focused approach early on is entirely because it is
>the easiest case to solve. Taking OVS as an example has the
>advantage of already being guarded by OpenFlow abstraction which
>by nature is very device oriented.

Yep, exactly.

>
>> It is not clear to me at this point whether we want those special
>> offloading devices to appear as separate net_device with specific
>> flags to advertise their offloading features (NAT, IP routing...) or
>> something else?
>
>One lesson that could serve as an example which differs from TOE is
>the offloading provided by recent FC HBAs. The device looks like a
>regular SCSI device to the kernel but offers a full DCB engine to
>allow for FCoE. The DCB bits can and must be configured. By not
>representing that engine with a net_device we cannot configure the
>engine through the Netlink interface dcbnl. dcbnl can certainly be
>extended to allow taking a scsi id of some sort instead of a ifindex
>but it's far from ideal.
>
>My take on this is that if it makes sense to use rtnl or ethtool
>to configure these offload engines then let's just go with a
>globally visible net_device and improve our capabilities system.
>
>> > But wouldn't you want to introduce an additional ndo to
>> > cover these?
>> 
>> I would start with making sure everyone is on the same page regarding
>> switches before we start building the conversation on NAT/IP-routing
>> offloading, but it is good that you mention it.
>
>Agreed

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 2/6] skbuff: add "missed_flow" flag
       [not found]   ` <1395851472-10524-3-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
  2014-03-26 16:59     ` Alexei Starovoitov
  2014-03-27 10:31     ` Nicolas Dichtel
@ 2014-03-31 20:39     ` Neil Jerram
  2 siblings, 0 replies; 31+ messages in thread
From: Neil Jerram @ 2014-03-31 20:39 UTC (permalink / raw
  To: 'Jiri Pirko',
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
	andy-QlMahl40kYEqcZcGjlUOXw@public.gmane.org,
	dev-yBygre7rU0TnMu66kgdUjQ@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,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR@public.gmane.org,
	jhs-jkUAjuhPggJWk0Htik3J/w@public.gmane.org,
	linville-2XuSBdqkA4R54TAoqtyWWQ@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,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org

> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 03db95a..0100c2f 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -567,6 +567,7 @@ struct sk_buff {
>  	 * headers if needed
>  	 */
>  	__u8			encapsulation:1;
> +	__u8			missed_flow:1;
>  	/* 6/8 bit hole (depending on ndisc_nodetype presence) */
>  	kmemcheck_bitfield_end(flags2);

Presumably you need to update the "6/8 bit hole" comment here.

Regards,
	Neil

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 4/6] net: introduce switchdev API
       [not found]   ` <1395851472-10524-5-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
@ 2014-03-31 20:47     ` Neil Jerram
  2014-03-31 20:55     ` Neil Jerram
  1 sibling, 0 replies; 31+ messages in thread
From: Neil Jerram @ 2014-03-31 20:47 UTC (permalink / raw
  To: 'Jiri Pirko',
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
	andy-QlMahl40kYEqcZcGjlUOXw@public.gmane.org,
	dev-yBygre7rU0TnMu66kgdUjQ@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,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR@public.gmane.org,
	jhs-jkUAjuhPggJWk0Htik3J/w@public.gmane.org,
	linville-2XuSBdqkA4R54TAoqtyWWQ@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,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org

> diff --git a/net/Kconfig b/net/Kconfig
> index e411046..e02ab8d 100644
> --- a/net/Kconfig
> +++ b/net/Kconfig
> @@ -285,6 +285,16 @@ config NET_FLOW_LIMIT
>  	  with many clients some protection against DoS by a single (spoofed)
>  	  flow that greatly exceeds average workload.
> 
> +config NET_SWITCHDEV
> +	tristate "Switch device"
> +	depends on INET
> +	---help---
> +	  This module provides glue for hardware switch chips so they can be
> +	  accessed from userspace via Open vSwitch Netlink API.
> +
> +	  To compile this code as a module, choose M here: the
> +	  module will be called pktgen.
> +

"pktgen" cut'n'paste typo.

	Neil

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [patch net-next RFC v2 4/6] net: introduce switchdev API
       [not found]   ` <1395851472-10524-5-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
  2014-03-31 20:47     ` Neil Jerram
@ 2014-03-31 20:55     ` Neil Jerram
  1 sibling, 0 replies; 31+ messages in thread
From: Neil Jerram @ 2014-03-31 20:55 UTC (permalink / raw
  To: 'Jiri Pirko',
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
  Cc: john.r.fastabend-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
	edumazet-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
	andy-QlMahl40kYEqcZcGjlUOXw@public.gmane.org,
	dev-yBygre7rU0TnMu66kgdUjQ@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,
	roopa-qUQiAmfTcIp+XZJcv9eMoEEOCMrvLtNR@public.gmane.org,
	jhs-jkUAjuhPggJWk0Htik3J/w@public.gmane.org,
	linville-2XuSBdqkA4R54TAoqtyWWQ@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,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org

Hi Jiri,

Apologies for possibly newbie questions here, but:

> +bool swdev_dev_check(const struct net_device *dev)
> +{
> +	return dev->priv_flags & IFF_SWITCH;
> +}
> +EXPORT_SYMBOL(swdev_dev_check);
[...]
> +	BUG_ON(!swdev_dev_check(dev));
[...]
> +int __swdev_register(struct net_device *dev)
> +{
> +	if (dev->priv_flags & IFF_SWITCH) {
> +		netdev_err(dev, "Device is already registered as a switch
> device\n");
> +		return -EBUSY;
> +	}
[...]

1. What's the benefit of requiring and policing the IFF_SWITCH flag, and requiring a switch netdev to call swdev_register, as opposed to just checking whether the netdev provides the relevant ops?

> +int swdev_register(struct net_device *dev)
> +{
> +	int err;
> +
> +	rtnl_lock();
> +	err = __swdev_register(dev);
> +	rtnl_unlock();
> +	return err;
> +}
> +EXPORT_SYMBOL(swdev_register);

2. Why grab and release the rtnl lock, given that there appears to be nothing rtnl-related in between?

Regards,
	Neil

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2014-03-31 20:55 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-26 16:31 [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath Jiri Pirko
2014-03-26 16:31 ` [patch net-next RFC v2 1/6] net: make packet_type->ak_packet_priv generic Jiri Pirko
2014-03-26 16:31 ` [patch net-next RFC v2 2/6] skbuff: add "missed_flow" flag Jiri Pirko
     [not found]   ` <1395851472-10524-3-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
2014-03-26 16:59     ` Alexei Starovoitov
2014-03-26 17:25       ` [ovs-dev] " Jiri Pirko
2014-03-27 10:31     ` Nicolas Dichtel
     [not found]       ` <5333FE0E.2090008-pdR9zngts4EAvxtiuMwx3w@public.gmane.org>
2014-03-27 10:34         ` Jiri Pirko
2014-03-31 20:39     ` Neil Jerram
2014-03-26 16:31 ` [patch net-next RFC v2 3/6] openvswitch: split flow structures into ovs specific and generic ones Jiri Pirko
2014-03-26 16:31 ` [patch net-next RFC v2 4/6] net: introduce switchdev API Jiri Pirko
2014-03-27 11:23   ` Thomas Graf
     [not found]     ` <20140327112339.GB1615-FZi0V3Vbi30CUdFEqe4BF2D2FQJk+8+b@public.gmane.org>
2014-03-27 11:26       ` Jiri Pirko
     [not found]   ` <1395851472-10524-5-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
2014-03-31 20:47     ` Neil Jerram
2014-03-31 20:55     ` Neil Jerram
2014-03-26 16:33 ` [patch iproute2 RFC v2] iproute: add support for dummyswport Jiri Pirko
     [not found] ` <1395851472-10524-1-git-send-email-jiri-rHqAuBHg3fBzbRFIqnYvSA@public.gmane.org>
2014-03-26 16:31   ` [patch net-next RFC v2 5/6] openvswitch: Introduce support for switchdev based datapath Jiri Pirko
2014-03-26 16:31   ` [patch net-next RFC v2 6/6] net: introduce dummy switch Jiri Pirko
2014-03-26 21:44   ` [patch net-next RFC v2 0/6] introduce infrastructure for support of switch chip datapath Jamal Hadi Salim
     [not found]     ` <53334A3F.6020105-jkUAjuhPggJWk0Htik3J/w@public.gmane.org>
2014-03-26 21:57       ` Florian Fainelli
     [not found]         ` <CAGVrzcaOph7=2WfMzTfqtwFkN1fu5uKJAH59aF7mqD4MwL7iOg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-03-27  7:23           ` Jiri Pirko
2014-03-27  7:21       ` Jiri Pirko
     [not found]         ` <20140327072107.GC2845-RDzucLLXGGI88b5SBfVpbw@public.gmane.org>
2014-03-27 10:27           ` Jamal Hadi Salim
2014-03-27 11:02             ` Thomas Graf
2014-03-27 11:17               ` Jamal Hadi Salim
     [not found]                 ` <533408C0.8000608-jkUAjuhPggJWk0Htik3J/w@public.gmane.org>
2014-03-27 12:00                   ` Thomas Graf
2014-03-27 12:32                     ` Jamal Hadi Salim
2014-03-27 12:57                       ` Jiri Pirko
     [not found]                         ` <20140327125711.GL2845-RDzucLLXGGI88b5SBfVpbw@public.gmane.org>
2014-03-27 14:03                           ` John W. Linville
2014-03-27 16:27               ` Florian Fainelli
2014-03-27 17:20                 ` Thomas Graf
     [not found]                   ` <20140327172048.GC13573-FZi0V3Vbi30CUdFEqe4BF2D2FQJk+8+b@public.gmane.org>
2014-03-27 17:26                     ` Jiri Pirko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.