* [RFC PATCH net-next 5/5] virtio-net: support XDP rx handler
From: Jason Wang @ 2018-08-13 3:05 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, jbrouer, mst, Jason Wang
In-Reply-To: <1534129513-4845-1-git-send-email-jasowang@redhat.com>
This patch tries to add the support of XDP rx handler to
virtio-net. This is straight-forward, just call xdp_do_pass() and
behave depends on its return value.
Test was done by using XDP_DROP (xdp1) for macvlan on top of
virtio-net. PPS of SKB mode was ~1.2Mpps while PPS of native XDP mode
was ~2.2Mpps. About 83% improvement was measured.
Notes: for RFC, only mergeable buffer case was implemented.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/virtio_net.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 62311dd..1e22ad9 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -777,6 +777,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
rcu_read_lock();
xdp_prog = rcu_dereference(rq->xdp_prog);
if (xdp_prog) {
+ rx_xdp_handler_result_t ret;
struct xdp_frame *xdpf;
struct page *xdp_page;
struct xdp_buff xdp;
@@ -825,6 +826,15 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
switch (act) {
case XDP_PASS:
+ ret = xdp_do_pass(&xdp);
+ if (ret == RX_XDP_HANDLER_DROP)
+ goto drop;
+ if (ret != RX_XDP_HANDLER_FALLBACK) {
+ if (unlikely(xdp_page != page))
+ put_page(page);
+ rcu_read_unlock();
+ goto xdp_xmit;
+ }
/* recalculate offset to account for any header
* adjustments. Note other cases do not build an
* skb and avoid using offset
@@ -881,6 +891,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
case XDP_ABORTED:
trace_xdp_exception(vi->dev, xdp_prog, act);
/* fall through */
+drop:
case XDP_DROP:
if (unlikely(xdp_page != page))
__free_pages(xdp_page, 0);
--
2.7.4
^ permalink raw reply related
* [RFC PATCH net-next V2 0/6] XDP rx handler
From: Jason Wang @ 2018-08-13 3:17 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, jbrouer, mst, Jason Wang
Hi:
This series tries to implement XDP support for rx hanlder. This would
be useful for doing native XDP on stacked device like macvlan, bridge
or even bond.
The idea is simple, let stacked device register a XDP rx handler. And
when driver return XDP_PASS, it will call a new helper xdp_do_pass()
which will try to pass XDP buff to XDP rx handler directly. XDP rx
handler may then decide how to proceed, it could consume the buff, ask
driver to drop the packet or ask the driver to fallback to normal skb
path.
A sample XDP rx handler was implemented for macvlan. And virtio-net
(mergeable buffer case) was converted to call xdp_do_pass() as an
example. For ease comparision, generic XDP support for rx handler was
also implemented.
Compared to skb mode XDP on macvlan, native XDP on macvlan (XDP_DROP)
shows about 83% improvement.
Please review.
Thanks
Jason Wang (6):
net: core: factor out generic XDP check and process routine
net: core: generic XDP support for stacked device
net: core: introduce XDP rx handler
macvlan: count the number of vlan in source mode
macvlan: basic XDP support
virtio-net: support XDP rx handler
drivers/net/macvlan.c | 189 +++++++++++++++++++++++++++++++++++++++++++--
drivers/net/virtio_net.c | 11 +++
include/linux/filter.h | 1 +
include/linux/if_macvlan.h | 1 +
include/linux/netdevice.h | 12 +++
net/core/dev.c | 69 +++++++++++++----
net/core/filter.c | 28 +++++++
7 files changed, 293 insertions(+), 18 deletions(-)
--
2.7.4
^ permalink raw reply
* [RFC PATCH net-next V2 1/6] net: core: factor out generic XDP check and process routine
From: Jason Wang @ 2018-08-13 3:17 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, jbrouer, mst, Jason Wang
In-Reply-To: <1534130250-5302-1-git-send-email-jasowang@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
net/core/dev.c | 35 ++++++++++++++++++++++-------------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index f68122f..605c66e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4392,13 +4392,9 @@ int do_xdp_generic(struct bpf_prog *xdp_prog, struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(do_xdp_generic);
-static int netif_rx_internal(struct sk_buff *skb)
+static int netif_do_generic_xdp(struct sk_buff *skb)
{
- int ret;
-
- net_timestamp_check(netdev_tstamp_prequeue, skb);
-
- trace_netif_rx(skb);
+ int ret = XDP_PASS;
if (static_branch_unlikely(&generic_xdp_needed_key)) {
int ret;
@@ -4408,15 +4404,28 @@ static int netif_rx_internal(struct sk_buff *skb)
ret = do_xdp_generic(rcu_dereference(skb->dev->xdp_prog), skb);
rcu_read_unlock();
preempt_enable();
-
- /* Consider XDP consuming the packet a success from
- * the netdev point of view we do not want to count
- * this as an error.
- */
- if (ret != XDP_PASS)
- return NET_RX_SUCCESS;
}
+ return ret;
+}
+
+static int netif_rx_internal(struct sk_buff *skb)
+{
+ int ret;
+
+ net_timestamp_check(netdev_tstamp_prequeue, skb);
+
+ trace_netif_rx(skb);
+
+ ret = netif_do_generic_xdp(skb);
+
+ /* Consider XDP consuming the packet a success from
+ * the netdev point of view we do not want to count
+ * this as an error.
+ */
+ if (ret != XDP_PASS)
+ return NET_RX_SUCCESS;
+
#ifdef CONFIG_RPS
if (static_key_false(&rps_needed)) {
struct rps_dev_flow voidflow, *rflow = &voidflow;
--
2.7.4
^ permalink raw reply related
* [RFC PATCH net-next V2 2/6] net: core: generic XDP support for stacked device
From: Jason Wang @ 2018-08-13 3:17 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, jbrouer, mst, Jason Wang
In-Reply-To: <1534130250-5302-1-git-send-email-jasowang@redhat.com>
Stacked device usually change skb->dev to its own and return
RX_HANDLER_ANOTHER during rx handler processing. But we don't call
generic XDP routine at that time, this means it can't work for stacked
device.
Fixing this by calling netif_do_generic_xdp() if rx handler returns
RX_HANDLER_ANOTHER. This allows us to do generic XDP on stacked device
e.g macvlan.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
net/core/dev.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/core/dev.c b/net/core/dev.c
index 605c66e..a77ce08 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4822,6 +4822,11 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc,
ret = NET_RX_SUCCESS;
goto out;
case RX_HANDLER_ANOTHER:
+ ret = netif_do_generic_xdp(skb);
+ if (ret != XDP_PASS) {
+ ret = NET_RX_SUCCESS;
+ goto out;
+ }
goto another_round;
case RX_HANDLER_EXACT:
deliver_exact = true;
--
2.7.4
^ permalink raw reply related
* [RFC PATCH net-next V2 3/6] net: core: introduce XDP rx handler
From: Jason Wang @ 2018-08-13 3:17 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, jbrouer, mst, Jason Wang
In-Reply-To: <1534130250-5302-1-git-send-email-jasowang@redhat.com>
This patch tries to introduce XDP rx handler. This will be used by
stacked device that depends on rx handler for having a fast packet
processing path based on XDP.
This idea is simple, when XDP program returns XDP_PASS, instead of
building skb immediately, driver will call xdp_do_pass() to check
whether or not there's a XDP rx handler, if yes, it will pass XDP
buffer to XDP rx handler first.
There are two main tasks for XDP rx handler, the first is check
whether or not the setup or packet could be processed through XDP buff
directly. The second task is to run XDP program. An XDP rx handler can
return several different results which was defined by enum
rx_xdp_handler_result_t:
RX_XDP_HANDLER_CONSUMED: This means the XDP buff were consumed.
RX_XDP_HANDLER_DROP: This means XDP rx handler ask to drop the packet.
RX_XDP_HANDLER_PASS_FALLBACK: This means XDP rx handler can not
process the packet (e.g cloning), and we need to fall back to normal
skb path to deal with the packet.
Consider we have the following configuration, Level 0 device which has
a rx handler for Level 1 device which has a rx handler for L2 device.
L2 device
|
L1 device
|
L0 device
With the help of XDP rx handler, we can attach XDP program on each of
the layer or even run native XDP handler for L2 without XDP prog
attached to L1 device:
(XDP prog for L2 device)
|
L2 XDP rx handler for L1
|
(XDP prog for L1 device)
|
L1 XDP rx hanlder for L0
|
XDP prog for L0 device
It works like: When the XDP program for L0 device returns XDP_PASS, we
will first try to check and pass XDP buff to its XDP rx handler if
there's one. Then the L1 XDP rx handler will be called and to run XDP
program for L1. When L1 XDP program returns XDP_PASS or there's no XDP
program attached to L1, we will try to call xdp_do_pass() to pass it
to XDP rx hanlder for L1. Then XDP buff will be passed to L2 XDP rx
handler etc. And it will try to run L2 XDP program if any. And if
there's no L2 XDP program or XDP program returns XDP_PASS. The handler
usually will build skb and call netif_rx() for a local receive. If any
of the XDP rx handlers returns XDP_RX_HANDLER_FALLBACK, the code will
return to L0 device and L0 device will try to build skb and go through
normal rx handler path for skb.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
include/linux/filter.h | 1 +
include/linux/netdevice.h | 12 ++++++++++++
net/core/dev.c | 29 +++++++++++++++++++++++++++++
net/core/filter.c | 28 ++++++++++++++++++++++++++++
4 files changed, 70 insertions(+)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index c73dd73..7cc8e69 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -791,6 +791,7 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
int xdp_do_redirect(struct net_device *dev,
struct xdp_buff *xdp,
struct bpf_prog *prog);
+rx_handler_result_t xdp_do_pass(struct xdp_buff *xdp);
void xdp_do_flush_map(void);
void bpf_warn_invalid_xdp_action(u32 act);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 282e2e9..21f0a9e 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -421,6 +421,14 @@ enum rx_handler_result {
typedef enum rx_handler_result rx_handler_result_t;
typedef rx_handler_result_t rx_handler_func_t(struct sk_buff **pskb);
+enum rx_xdp_handler_result {
+ RX_XDP_HANDLER_CONSUMED,
+ RX_XDP_HANDLER_DROP,
+ RX_XDP_HANDLER_FALLBACK,
+};
+typedef enum rx_xdp_handler_result rx_xdp_handler_result_t;
+typedef rx_xdp_handler_result_t rx_xdp_handler_func_t(struct net_device *dev,
+ struct xdp_buff *xdp);
void __napi_schedule(struct napi_struct *n);
void __napi_schedule_irqoff(struct napi_struct *n);
@@ -1898,6 +1906,7 @@ struct net_device {
struct bpf_prog __rcu *xdp_prog;
unsigned long gro_flush_timeout;
rx_handler_func_t __rcu *rx_handler;
+ rx_xdp_handler_func_t __rcu *rx_xdp_handler;
void __rcu *rx_handler_data;
#ifdef CONFIG_NET_CLS_ACT
@@ -3530,7 +3539,10 @@ bool netdev_is_rx_handler_busy(struct net_device *dev);
int netdev_rx_handler_register(struct net_device *dev,
rx_handler_func_t *rx_handler,
void *rx_handler_data);
+int netdev_rx_xdp_handler_register(struct net_device *dev,
+ rx_xdp_handler_func_t *rx_xdp_handler);
void netdev_rx_handler_unregister(struct net_device *dev);
+void netdev_rx_xdp_handler_unregister(struct net_device *dev);
bool dev_valid_name(const char *name);
int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
diff --git a/net/core/dev.c b/net/core/dev.c
index a77ce08..b4e8949 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4638,6 +4638,12 @@ bool netdev_is_rx_handler_busy(struct net_device *dev)
}
EXPORT_SYMBOL_GPL(netdev_is_rx_handler_busy);
+static bool netdev_is_rx_xdp_handler_busy(struct net_device *dev)
+{
+ ASSERT_RTNL();
+ return dev && rtnl_dereference(dev->rx_xdp_handler);
+}
+
/**
* netdev_rx_handler_register - register receive handler
* @dev: device to register a handler for
@@ -4670,6 +4676,22 @@ int netdev_rx_handler_register(struct net_device *dev,
}
EXPORT_SYMBOL_GPL(netdev_rx_handler_register);
+int netdev_rx_xdp_handler_register(struct net_device *dev,
+ rx_xdp_handler_func_t *rx_xdp_handler)
+{
+ if (netdev_is_rx_xdp_handler_busy(dev))
+ return -EBUSY;
+
+ if (dev->priv_flags & IFF_NO_RX_HANDLER)
+ return -EINVAL;
+
+ rcu_assign_pointer(dev->rx_xdp_handler, rx_xdp_handler);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(netdev_rx_xdp_handler_register);
+
+
/**
* netdev_rx_handler_unregister - unregister receive handler
* @dev: device to unregister a handler from
@@ -4692,6 +4714,13 @@ void netdev_rx_handler_unregister(struct net_device *dev)
}
EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
+void netdev_rx_xdp_handler_unregister(struct net_device *dev)
+{
+ ASSERT_RTNL();
+ RCU_INIT_POINTER(dev->rx_xdp_handler, NULL);
+}
+EXPORT_SYMBOL_GPL(netdev_rx_xdp_handler_unregister);
+
/*
* Limit the use of PFMEMALLOC reserves to those protocols that implement
* the special handling of PFMEMALLOC skbs.
diff --git a/net/core/filter.c b/net/core/filter.c
index 587bbfb..9ea3797 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3312,6 +3312,34 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
}
EXPORT_SYMBOL_GPL(xdp_do_redirect);
+rx_handler_result_t xdp_do_pass(struct xdp_buff *xdp)
+{
+ rx_xdp_handler_result_t ret;
+ rx_xdp_handler_func_t *rx_xdp_handler;
+ struct net_device *dev = xdp->rxq->dev;
+
+ ret = RX_XDP_HANDLER_FALLBACK;
+ rx_xdp_handler = rcu_dereference(dev->rx_xdp_handler);
+
+ if (rx_xdp_handler) {
+ ret = rx_xdp_handler(dev, xdp);
+ switch (ret) {
+ case RX_XDP_HANDLER_CONSUMED:
+ /* Fall through */
+ case RX_XDP_HANDLER_DROP:
+ /* Fall through */
+ case RX_XDP_HANDLER_FALLBACK:
+ break;
+ default:
+ BUG();
+ break;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(xdp_do_pass);
+
static int xdp_do_generic_redirect_map(struct net_device *dev,
struct sk_buff *skb,
struct xdp_buff *xdp,
--
2.7.4
^ permalink raw reply related
* [RFC PATCH net-next V2 4/6] macvlan: count the number of vlan in source mode
From: Jason Wang @ 2018-08-13 3:17 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, jbrouer, mst, Jason Wang
In-Reply-To: <1534130250-5302-1-git-send-email-jasowang@redhat.com>
This patch tries to count the number of vlans in source mode. This
will be used for implementing XDP rx handler for macvlan.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/macvlan.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index cfda146..b7c814d 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -53,6 +53,7 @@ struct macvlan_port {
struct hlist_head vlan_source_hash[MACVLAN_HASH_SIZE];
DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ);
unsigned char perm_addr[ETH_ALEN];
+ unsigned long source_count;
};
struct macvlan_source_entry {
@@ -1433,6 +1434,9 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
if (err)
goto unregister_netdev;
+ if (vlan->mode == MACVLAN_MODE_SOURCE)
+ port->source_count++;
+
list_add_tail_rcu(&vlan->list, &port->vlans);
netif_stacked_transfer_operstate(lowerdev, dev);
linkwatch_fire_event(dev);
@@ -1477,6 +1481,7 @@ static int macvlan_changelink(struct net_device *dev,
struct netlink_ext_ack *extack)
{
struct macvlan_dev *vlan = netdev_priv(dev);
+ struct macvlan_port *port = vlan->port;
enum macvlan_mode mode;
bool set_mode = false;
enum macvlan_macaddr_mode macmode;
@@ -1491,8 +1496,10 @@ static int macvlan_changelink(struct net_device *dev,
(vlan->mode == MACVLAN_MODE_PASSTHRU))
return -EINVAL;
if (vlan->mode == MACVLAN_MODE_SOURCE &&
- vlan->mode != mode)
+ vlan->mode != mode) {
macvlan_flush_sources(vlan->port, vlan);
+ port->source_count--;
+ }
}
if (data && data[IFLA_MACVLAN_FLAGS]) {
@@ -1510,8 +1517,13 @@ static int macvlan_changelink(struct net_device *dev,
}
vlan->flags = flags;
}
- if (set_mode)
+ if (set_mode) {
vlan->mode = mode;
+ if (mode == MACVLAN_MODE_SOURCE &&
+ vlan->mode != mode) {
+ port->source_count++;
+ }
+ }
if (data && data[IFLA_MACVLAN_MACADDR_MODE]) {
if (vlan->mode != MACVLAN_MODE_SOURCE)
return -EINVAL;
--
2.7.4
^ permalink raw reply related
* [RFC PATCH net-next V2 5/6] macvlan: basic XDP support
From: Jason Wang @ 2018-08-13 3:17 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, jbrouer, mst, Jason Wang
In-Reply-To: <1534130250-5302-1-git-send-email-jasowang@redhat.com>
This patch tries to implementing basic XDP support for macvlan. The
implementation was split into two parts:
1) XDP rx handler of underlay device:
We will register an XDP rx handler (macvlan_handle_xdp) to under layer
device. In this handler, we will the following cases to go for slow
path (XDP_RX_HANDLER_PASS):
- The packet is a multicast packet.
- A vlan is source mode
- Destination mac address does not match any vlan
If none of the above cases were true, it means we could go for XDP
path directly. We will change the dev and return
RX_XDP_HANDLER_ANOTHER.
2) If we find a destination vlan, we will try to run XDP prog.
If XDP prog return XDP_PASS, we will call xdp_do_pass() to pass it to
up layer XDP rx handler. This is needed for e.g macvtap to work. If
XDP_RX_HANDLER_FALLBACK is returned, we will build skb and call
netif_rx() to finish the receiving. Otherwise just return the result
to lower device. For XDP_TX, we will build skb and try XDP generic
transmission routine for simplicity. This could be optimized on top.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/macvlan.c | 173 ++++++++++++++++++++++++++++++++++++++++++++-
include/linux/if_macvlan.h | 1 +
2 files changed, 171 insertions(+), 3 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index b7c814d..42b747c 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -34,6 +34,7 @@
#include <net/rtnetlink.h>
#include <net/xfrm.h>
#include <linux/netpoll.h>
+#include <linux/bpf.h>
#define MACVLAN_HASH_BITS 8
#define MACVLAN_HASH_SIZE (1<<MACVLAN_HASH_BITS)
@@ -436,6 +437,122 @@ static void macvlan_forward_source(struct sk_buff *skb,
}
}
+struct sk_buff *macvlan_xdp_build_skb(struct net_device *dev,
+ struct xdp_buff *xdp)
+{
+ int len;
+ int buflen = xdp->data_end - xdp->data_hard_start;
+ int headroom = xdp->data - xdp->data_hard_start;
+ struct sk_buff *skb;
+
+ len = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + headroom +
+ SKB_DATA_ALIGN(buflen);
+
+ skb = build_skb(xdp->data_hard_start, len);
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, headroom);
+ __skb_put(skb, xdp->data_end - xdp->data);
+
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->dev = dev;
+
+ return skb;
+}
+
+static rx_xdp_handler_result_t macvlan_receive_xdp(struct net_device *dev,
+ struct xdp_buff *xdp)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct bpf_prog *xdp_prog;
+ struct sk_buff *skb;
+ u32 act = XDP_PASS;
+ rx_xdp_handler_result_t ret;
+ int err;
+
+ rcu_read_lock();
+ xdp_prog = rcu_dereference(vlan->xdp_prog);
+
+ if (xdp_prog)
+ act = bpf_prog_run_xdp(xdp_prog, xdp);
+
+ switch (act) {
+ case XDP_PASS:
+ ret = xdp_do_pass(xdp);
+ if (ret != RX_XDP_HANDLER_FALLBACK) {
+ rcu_read_unlock();
+ return ret;
+ }
+ skb = macvlan_xdp_build_skb(dev, xdp);
+ if (!skb) {
+ act = XDP_DROP;
+ break;
+ }
+ rcu_read_unlock();
+ netif_rx(skb);
+ macvlan_count_rx(vlan, skb->len, true, false);
+ goto out;
+ case XDP_TX:
+ skb = macvlan_xdp_build_skb(dev, xdp);
+ if (!skb) {
+ act = XDP_DROP;
+ break;
+ }
+ generic_xdp_tx(skb, xdp_prog);
+ break;
+ case XDP_REDIRECT:
+ err = xdp_do_redirect(dev, xdp, xdp_prog);
+ xdp_do_flush_map();
+ if (err)
+ act = XDP_DROP;
+ break;
+ case XDP_DROP:
+ break;
+ default:
+ bpf_warn_invalid_xdp_action(act);
+ break;
+ }
+
+ rcu_read_unlock();
+out:
+ if (act == XDP_DROP)
+ return RX_XDP_HANDLER_DROP;
+
+ return RX_XDP_HANDLER_CONSUMED;
+}
+
+/* called under rcu_read_lock() from XDP handler */
+static rx_xdp_handler_result_t macvlan_handle_xdp(struct net_device *dev,
+ struct xdp_buff *xdp)
+{
+ const struct ethhdr *eth = (const struct ethhdr *)xdp->data;
+ struct macvlan_port *port;
+ struct macvlan_dev *vlan;
+
+ if (is_multicast_ether_addr(eth->h_dest))
+ return RX_XDP_HANDLER_FALLBACK;
+
+ port = macvlan_port_get_rcu(dev);
+ if (port->source_count)
+ return RX_XDP_HANDLER_FALLBACK;
+
+ if (macvlan_passthru(port))
+ vlan = list_first_or_null_rcu(&port->vlans,
+ struct macvlan_dev, list);
+ else
+ vlan = macvlan_hash_lookup(port, eth->h_dest);
+
+ if (!vlan)
+ return RX_XDP_HANDLER_FALLBACK;
+
+ dev = vlan->dev;
+ if (unlikely(!(dev->flags & IFF_UP)))
+ return RX_XDP_HANDLER_DROP;
+
+ return macvlan_receive_xdp(dev, xdp);
+}
+
/* called under rcu_read_lock() from netif_receive_skb */
static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
{
@@ -1089,6 +1206,44 @@ static int macvlan_dev_get_iflink(const struct net_device *dev)
return vlan->lowerdev->ifindex;
}
+static int macvlan_xdp_set(struct net_device *dev, struct bpf_prog *prog,
+ struct netlink_ext_ack *extack)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct bpf_prog *old_prog = rtnl_dereference(vlan->xdp_prog);
+
+ rcu_assign_pointer(vlan->xdp_prog, prog);
+
+ if (old_prog)
+ bpf_prog_put(old_prog);
+
+ return 0;
+}
+
+static u32 macvlan_xdp_query(struct net_device *dev)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ const struct bpf_prog *xdp_prog = rtnl_dereference(vlan->xdp_prog);
+
+ if (xdp_prog)
+ return xdp_prog->aux->id;
+
+ return 0;
+}
+
+static int macvlan_xdp(struct net_device *dev, struct netdev_bpf *xdp)
+{
+ switch (xdp->command) {
+ case XDP_SETUP_PROG:
+ return macvlan_xdp_set(dev, xdp->prog, xdp->extack);
+ case XDP_QUERY_PROG:
+ xdp->prog_id = macvlan_xdp_query(dev);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
static const struct ethtool_ops macvlan_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_link_ksettings = macvlan_ethtool_get_link_ksettings,
@@ -1121,6 +1276,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
#endif
.ndo_get_iflink = macvlan_dev_get_iflink,
.ndo_features_check = passthru_features_check,
+ .ndo_bpf = macvlan_xdp,
};
void macvlan_common_setup(struct net_device *dev)
@@ -1173,10 +1329,20 @@ static int macvlan_port_create(struct net_device *dev)
INIT_WORK(&port->bc_work, macvlan_process_broadcast);
err = netdev_rx_handler_register(dev, macvlan_handle_frame, port);
- if (err)
+ if (err) {
kfree(port);
- else
- dev->priv_flags |= IFF_MACVLAN_PORT;
+ goto out;
+ }
+
+ err = netdev_rx_xdp_handler_register(dev, macvlan_handle_xdp);
+ if (err) {
+ netdev_rx_handler_unregister(dev);
+ kfree(port);
+ goto out;
+ }
+
+ dev->priv_flags |= IFF_MACVLAN_PORT;
+out:
return err;
}
@@ -1187,6 +1353,7 @@ static void macvlan_port_destroy(struct net_device *dev)
dev->priv_flags &= ~IFF_MACVLAN_PORT;
netdev_rx_handler_unregister(dev);
+ netdev_rx_xdp_handler_unregister(dev);
/* After this point, no packet can schedule bc_work anymore,
* but we need to cancel it and purge left skbs if any.
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index 2e55e4c..7c7059b 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -34,6 +34,7 @@ struct macvlan_dev {
#ifdef CONFIG_NET_POLL_CONTROLLER
struct netpoll *netpoll;
#endif
+ struct bpf_prog __rcu *xdp_prog;
};
static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
--
2.7.4
^ permalink raw reply related
* [RFC PATCH net-next V2 6/6] virtio-net: support XDP rx handler
From: Jason Wang @ 2018-08-13 3:17 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, jbrouer, mst, Jason Wang
In-Reply-To: <1534130250-5302-1-git-send-email-jasowang@redhat.com>
This patch tries to add the support of XDP rx handler to
virtio-net. This is straight-forward, just call xdp_do_pass() and
behave depends on its return value.
Test was done by using XDP_DROP (xdp1) for macvlan on top of
virtio-net. PPS of SKB mode was ~1.2Mpps while PPS of native XDP mode
was ~2.2Mpps. About 83% improvement was measured.
Notes: for RFC, only mergeable buffer case was implemented.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/virtio_net.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 62311dd..1e22ad9 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -777,6 +777,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
rcu_read_lock();
xdp_prog = rcu_dereference(rq->xdp_prog);
if (xdp_prog) {
+ rx_xdp_handler_result_t ret;
struct xdp_frame *xdpf;
struct page *xdp_page;
struct xdp_buff xdp;
@@ -825,6 +826,15 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
switch (act) {
case XDP_PASS:
+ ret = xdp_do_pass(&xdp);
+ if (ret == RX_XDP_HANDLER_DROP)
+ goto drop;
+ if (ret != RX_XDP_HANDLER_FALLBACK) {
+ if (unlikely(xdp_page != page))
+ put_page(page);
+ rcu_read_unlock();
+ goto xdp_xmit;
+ }
/* recalculate offset to account for any header
* adjustments. Note other cases do not build an
* skb and avoid using offset
@@ -881,6 +891,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
case XDP_ABORTED:
trace_xdp_exception(vi->dev, xdp_prog, act);
/* fall through */
+drop:
case XDP_DROP:
if (unlikely(xdp_page != page))
__free_pages(xdp_page, 0);
--
2.7.4
^ permalink raw reply related
* Re: [RFC PATCH net-next 0/5] XDP rx handler
From: Jason Wang @ 2018-08-13 3:17 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, jbrouer, mst
In-Reply-To: <1534129513-4845-1-git-send-email-jasowang@redhat.com>
On 2018年08月13日 11:05, Jason Wang wrote:
> Hi:
>
> This series tries to implement XDP support for rx hanlder. This would
> be useful for doing native XDP on stacked device like macvlan, bridge
> or even bond.
>
> The idea is simple, let stacked device register a XDP rx handler. And
> when driver return XDP_PASS, it will call a new helper xdp_do_pass()
> which will try to pass XDP buff to XDP rx handler directly. XDP rx
> handler may then decide how to proceed, it could consume the buff, ask
> driver to drop the packet or ask the driver to fallback to normal skb
> path.
>
> A sample XDP rx handler was implemented for macvlan. And virtio-net
> (mergeable buffer case) was converted to call xdp_do_pass() as an
> example. For ease comparision, generic XDP support for rx handler was
> also implemented.
>
> Compared to skb mode XDP on macvlan, native XDP on macvlan (XDP_DROP)
> shows about 83% improvement.
>
> Please review.
>
> Thanks
>
> Jason Wang (5):
> net: core: generic XDP support for stacked device
> net: core: introduce XDP rx handler
> macvlan: count the number of vlan in source mode
> macvlan: basic XDP support
> virtio-net: support XDP rx handler
>
> drivers/net/macvlan.c | 189 +++++++++++++++++++++++++++++++++++++++++++--
> drivers/net/virtio_net.c | 11 +++
> include/linux/filter.h | 1 +
> include/linux/if_macvlan.h | 1 +
> include/linux/netdevice.h | 12 +++
> net/core/dev.c | 34 ++++++++
> net/core/filter.c | 28 +++++++
> 7 files changed, 271 insertions(+), 5 deletions(-)
>
Looks like a patch is missed. Let me post V2.
Thanks
^ permalink raw reply
* Re: [PATCH net-next] openvswitch: Derive IP protocol number for IPv6 later frags
From: Pravin Shelar @ 2018-08-13 1:09 UTC (permalink / raw)
To: Yi-Hung Wei; +Cc: Linux Kernel Network Developers, William Tu
In-Reply-To: <1533921581-22806-1-git-send-email-yihung.wei@gmail.com>
On Fri, Aug 10, 2018 at 10:19 AM, Yi-Hung Wei <yihung.wei@gmail.com> wrote:
> Currently, OVS only parses the IP protocol number for the first
> IPv6 fragment, but sets the IP protocol number for the later fragments
> to be NEXTHDF_FRAGMENT. This patch tries to derive the IP protocol
> number for the IPV6 later frags so that we can match that.
>
> Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
> ---
> net/openvswitch/flow.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
> index 56b8e7167790..3d654c4f71be 100644
> --- a/net/openvswitch/flow.c
> +++ b/net/openvswitch/flow.c
> @@ -297,7 +297,13 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
>
> nh_len = payload_ofs - nh_ofs;
> skb_set_transport_header(skb, nh_ofs + nh_len);
> - key->ip.proto = nexthdr;
> + if (key->ip.frag == OVS_FRAG_TYPE_LATER) {
> + unsigned int offset = 0;
> +
> + key->ip.proto = ipv6_find_hdr(skb, &offset, -1, NULL, NULL);
> + } else {
> + key->ip.proto = nexthdr;
> + }
parsing ipv6 ipv6_skip_exthdr() is called to find fragment hdr and
then this patch calls ipv6_find_hdr() to find next protocol. I think
we could call ipv6_find_hdr() to get fragment type and next hdr, that
would save parsing same packet twice in some cases.
Other option would be calling ipv6_find_hdr() after setting OVS_FRAG_TYPE_LATER.
^ permalink raw reply
* Re: [PATCH] mt76: Enable NL80211_EXT_FEATURE_CQM_RSSI_LIST
From: Kristian Evensen @ 2018-08-13 4:58 UTC (permalink / raw)
To: arend.vanspriel; +Cc: kvalo, linux-wireless, Network Development, linux-kernel
In-Reply-To: <5B708025.4090906@broadcom.com>
Hi Kalle & Arnd,
On Sun, Aug 12, 2018 at 8:44 PM Arend van Spriel
<arend.vanspriel@broadcom.com> wrote:
> > So have you tested this and with what devices? For example, does it work
> > with recently added USB devices?
>
> I was looking into this as it looks suspicious to me. From reading the
> description of this ext_feature flag it seems this is an extention of CQM:
Thank you very much for your feedback. My commit message should have
been more detailed, sorry about that. I have checked that the flag
works as intended with mt7602-, mt7603- and mt7612-based wifi cards. I
have not had the opportunity to test with any of the recently added
USB devices, as I don't have access to any of those.
In order to test the flag, I wrote a small program which subscribes to
the CQM-multicast group, passes an RSSI threshold-list to the kernel
and logs the received CQM-events. I then disconnected and connected
the wifi-antennas of the different cards. My threshold list was {-70,
-60, -50, -40} and while unscrewing the antenna I received multiple
below-events. When I attached the antenna again, I received multiple
above-events. As an example, here is the log when I tested with mt7612
(singal level when starting was ~-48 dBm):
Requested nl80211 generic netlink id
nl80211 has generic netlink id: 23
mlme ID is 5
Added socket to mlme group
Sent NL80211_CMD_SET_CQM
No error
Wifi (idx 18) went below threshold. RSSI -52
Wifi (idx 18) went above threshold. RSSI -49
Wifi (idx 18) went below threshold. RSSI -52
Wifi (idx 18) went below threshold. RSSI -62
Wifi (idx 18) went above threshold. RSSI -59
Wifi (idx 18) went above threshold. RSSI -49
Based on how I interpret the output and my understanding of how CQM +
RSSI_LIST works, this output shows that mt76 works fine with
NL80211_EXT_FEATURE_CQM_RSSI_LIST (at least for my cards). The list
was interpreted and handled correctly, as I received events when the
RSSI passed different thresholds in my list (-50, -60).
BR,
Kristian
^ permalink raw reply
* [PATCH][net-next][v2] packet: switch kvzalloc to allocate memory
From: Li RongQing @ 2018-08-13 2:42 UTC (permalink / raw)
To: netdev
The patches includes following change:
*Use modern kvzalloc()/kvfree() instead of custom allocations.
*Remove order argument for alloc_pg_vec, it can get from req.
*Remove order argument for free_pg_vec, free_pg_vec now uses
kvfree which does not need order argument.
*Remove pg_vec_order from struct packet_ring_buffer, no longer
need to save/restore 'order'
*Remove variable 'order' for packet_set_ring, it is now unused
Signed-off-by: Zhang Yu <zhangyu31@baidu.com>
Signed-off-by: Li RongQing <lirongqing@baidu.com>
---
net/packet/af_packet.c | 44 +++++++++++++-------------------------------
net/packet/internal.h | 1 -
2 files changed, 13 insertions(+), 32 deletions(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 75c92a87e7b2..5610061e7f2e 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4137,52 +4137,36 @@ static const struct vm_operations_struct packet_mmap_ops = {
.close = packet_mm_close,
};
-static void free_pg_vec(struct pgv *pg_vec, unsigned int order,
- unsigned int len)
+static void free_pg_vec(struct pgv *pg_vec, unsigned int len)
{
int i;
for (i = 0; i < len; i++) {
if (likely(pg_vec[i].buffer)) {
- if (is_vmalloc_addr(pg_vec[i].buffer))
- vfree(pg_vec[i].buffer);
- else
- free_pages((unsigned long)pg_vec[i].buffer,
- order);
+ kvfree(pg_vec[i].buffer);
pg_vec[i].buffer = NULL;
}
}
kfree(pg_vec);
}
-static char *alloc_one_pg_vec_page(unsigned long order)
+static char *alloc_one_pg_vec_page(unsigned long size)
{
char *buffer;
- gfp_t gfp_flags = GFP_KERNEL | __GFP_COMP |
- __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY;
- buffer = (char *) __get_free_pages(gfp_flags, order);
+ buffer = kvzalloc(size, GFP_KERNEL);
if (buffer)
return buffer;
- /* __get_free_pages failed, fall back to vmalloc */
- buffer = vzalloc(array_size((1 << order), PAGE_SIZE));
- if (buffer)
- return buffer;
+ buffer = kvzalloc(size, GFP_KERNEL | __GFP_RETRY_MAYFAIL);
- /* vmalloc failed, lets dig into swap here */
- gfp_flags &= ~__GFP_NORETRY;
- buffer = (char *) __get_free_pages(gfp_flags, order);
- if (buffer)
- return buffer;
-
- /* complete and utter failure */
- return NULL;
+ return buffer;
}
-static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order)
+static struct pgv *alloc_pg_vec(struct tpacket_req *req)
{
unsigned int block_nr = req->tp_block_nr;
+ unsigned long size = req->tp_block_size;
struct pgv *pg_vec;
int i;
@@ -4191,7 +4175,7 @@ static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order)
goto out;
for (i = 0; i < block_nr; i++) {
- pg_vec[i].buffer = alloc_one_pg_vec_page(order);
+ pg_vec[i].buffer = alloc_one_pg_vec_page(size);
if (unlikely(!pg_vec[i].buffer))
goto out_free_pgvec;
}
@@ -4200,7 +4184,7 @@ static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order)
return pg_vec;
out_free_pgvec:
- free_pg_vec(pg_vec, order, block_nr);
+ free_pg_vec(pg_vec, block_nr);
pg_vec = NULL;
goto out;
}
@@ -4210,9 +4194,9 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
{
struct pgv *pg_vec = NULL;
struct packet_sock *po = pkt_sk(sk);
- int was_running, order = 0;
struct packet_ring_buffer *rb;
struct sk_buff_head *rb_queue;
+ int was_running;
__be16 num;
int err = -EINVAL;
/* Added to avoid minimal code churn */
@@ -4274,8 +4258,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
goto out;
err = -ENOMEM;
- order = get_order(req->tp_block_size);
- pg_vec = alloc_pg_vec(req, order);
+ pg_vec = alloc_pg_vec(req);
if (unlikely(!pg_vec))
goto out;
switch (po->tp_version) {
@@ -4329,7 +4312,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
rb->frame_size = req->tp_frame_size;
spin_unlock_bh(&rb_queue->lock);
- swap(rb->pg_vec_order, order);
swap(rb->pg_vec_len, req->tp_block_nr);
rb->pg_vec_pages = req->tp_block_size/PAGE_SIZE;
@@ -4355,7 +4337,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
}
if (pg_vec)
- free_pg_vec(pg_vec, order, req->tp_block_nr);
+ free_pg_vec(pg_vec, req->tp_block_nr);
out:
return err;
}
diff --git a/net/packet/internal.h b/net/packet/internal.h
index 3bb7c5fb3bff..8f50036f62f0 100644
--- a/net/packet/internal.h
+++ b/net/packet/internal.h
@@ -64,7 +64,6 @@ struct packet_ring_buffer {
unsigned int frame_size;
unsigned int frame_max;
- unsigned int pg_vec_order;
unsigned int pg_vec_pages;
unsigned int pg_vec_len;
--
2.16.2
^ permalink raw reply related
* [RFC PATCH net-next 0/5] XDP rx handler
From: Jason Wang @ 2018-08-13 3:05 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, jbrouer, mst, Jason Wang
Hi:
This series tries to implement XDP support for rx hanlder. This would
be useful for doing native XDP on stacked device like macvlan, bridge
or even bond.
The idea is simple, let stacked device register a XDP rx handler. And
when driver return XDP_PASS, it will call a new helper xdp_do_pass()
which will try to pass XDP buff to XDP rx handler directly. XDP rx
handler may then decide how to proceed, it could consume the buff, ask
driver to drop the packet or ask the driver to fallback to normal skb
path.
A sample XDP rx handler was implemented for macvlan. And virtio-net
(mergeable buffer case) was converted to call xdp_do_pass() as an
example. For ease comparision, generic XDP support for rx handler was
also implemented.
Compared to skb mode XDP on macvlan, native XDP on macvlan (XDP_DROP)
shows about 83% improvement.
Please review.
Thanks
Jason Wang (5):
net: core: generic XDP support for stacked device
net: core: introduce XDP rx handler
macvlan: count the number of vlan in source mode
macvlan: basic XDP support
virtio-net: support XDP rx handler
drivers/net/macvlan.c | 189 +++++++++++++++++++++++++++++++++++++++++++--
drivers/net/virtio_net.c | 11 +++
include/linux/filter.h | 1 +
include/linux/if_macvlan.h | 1 +
include/linux/netdevice.h | 12 +++
net/core/dev.c | 34 ++++++++
net/core/filter.c | 28 +++++++
7 files changed, 271 insertions(+), 5 deletions(-)
--
2.7.4
^ permalink raw reply
* [RFC PATCH net-next 4/5] macvlan: basic XDP support
From: Jason Wang @ 2018-08-13 3:05 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: ast, daniel, jbrouer, mst, Jason Wang
In-Reply-To: <1534129513-4845-1-git-send-email-jasowang@redhat.com>
This patch tries to implementing basic XDP support for macvlan. The
implementation was split into two parts:
1) XDP rx handler of underlay device:
We will register an XDP rx handler (macvlan_handle_xdp) to under layer
device. In this handler, we will the following cases to go for slow
path (XDP_RX_HANDLER_PASS):
- The packet is a multicast packet.
- A vlan is source mode
- Destination mac address does not match any vlan
If none of the above cases were true, it means we could go for XDP
path directly. We will change the dev and return
RX_XDP_HANDLER_ANOTHER.
2) If we find a destination vlan, we will try to run XDP prog.
If XDP prog return XDP_PASS, we will call xdp_do_pass() to pass it to
up layer XDP rx handler. This is needed for e.g macvtap to work. If
XDP_RX_HANDLER_FALLBACK is returned, we will build skb and call
netif_rx() to finish the receiving. Otherwise just return the result
to lower device. For XDP_TX, we will build skb and try XDP generic
transmission routine for simplicity. This could be optimized on top.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/macvlan.c | 173 ++++++++++++++++++++++++++++++++++++++++++++-
include/linux/if_macvlan.h | 1 +
2 files changed, 171 insertions(+), 3 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index b7c814d..42b747c 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -34,6 +34,7 @@
#include <net/rtnetlink.h>
#include <net/xfrm.h>
#include <linux/netpoll.h>
+#include <linux/bpf.h>
#define MACVLAN_HASH_BITS 8
#define MACVLAN_HASH_SIZE (1<<MACVLAN_HASH_BITS)
@@ -436,6 +437,122 @@ static void macvlan_forward_source(struct sk_buff *skb,
}
}
+struct sk_buff *macvlan_xdp_build_skb(struct net_device *dev,
+ struct xdp_buff *xdp)
+{
+ int len;
+ int buflen = xdp->data_end - xdp->data_hard_start;
+ int headroom = xdp->data - xdp->data_hard_start;
+ struct sk_buff *skb;
+
+ len = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + headroom +
+ SKB_DATA_ALIGN(buflen);
+
+ skb = build_skb(xdp->data_hard_start, len);
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, headroom);
+ __skb_put(skb, xdp->data_end - xdp->data);
+
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->dev = dev;
+
+ return skb;
+}
+
+static rx_xdp_handler_result_t macvlan_receive_xdp(struct net_device *dev,
+ struct xdp_buff *xdp)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct bpf_prog *xdp_prog;
+ struct sk_buff *skb;
+ u32 act = XDP_PASS;
+ rx_xdp_handler_result_t ret;
+ int err;
+
+ rcu_read_lock();
+ xdp_prog = rcu_dereference(vlan->xdp_prog);
+
+ if (xdp_prog)
+ act = bpf_prog_run_xdp(xdp_prog, xdp);
+
+ switch (act) {
+ case XDP_PASS:
+ ret = xdp_do_pass(xdp);
+ if (ret != RX_XDP_HANDLER_FALLBACK) {
+ rcu_read_unlock();
+ return ret;
+ }
+ skb = macvlan_xdp_build_skb(dev, xdp);
+ if (!skb) {
+ act = XDP_DROP;
+ break;
+ }
+ rcu_read_unlock();
+ netif_rx(skb);
+ macvlan_count_rx(vlan, skb->len, true, false);
+ goto out;
+ case XDP_TX:
+ skb = macvlan_xdp_build_skb(dev, xdp);
+ if (!skb) {
+ act = XDP_DROP;
+ break;
+ }
+ generic_xdp_tx(skb, xdp_prog);
+ break;
+ case XDP_REDIRECT:
+ err = xdp_do_redirect(dev, xdp, xdp_prog);
+ xdp_do_flush_map();
+ if (err)
+ act = XDP_DROP;
+ break;
+ case XDP_DROP:
+ break;
+ default:
+ bpf_warn_invalid_xdp_action(act);
+ break;
+ }
+
+ rcu_read_unlock();
+out:
+ if (act == XDP_DROP)
+ return RX_XDP_HANDLER_DROP;
+
+ return RX_XDP_HANDLER_CONSUMED;
+}
+
+/* called under rcu_read_lock() from XDP handler */
+static rx_xdp_handler_result_t macvlan_handle_xdp(struct net_device *dev,
+ struct xdp_buff *xdp)
+{
+ const struct ethhdr *eth = (const struct ethhdr *)xdp->data;
+ struct macvlan_port *port;
+ struct macvlan_dev *vlan;
+
+ if (is_multicast_ether_addr(eth->h_dest))
+ return RX_XDP_HANDLER_FALLBACK;
+
+ port = macvlan_port_get_rcu(dev);
+ if (port->source_count)
+ return RX_XDP_HANDLER_FALLBACK;
+
+ if (macvlan_passthru(port))
+ vlan = list_first_or_null_rcu(&port->vlans,
+ struct macvlan_dev, list);
+ else
+ vlan = macvlan_hash_lookup(port, eth->h_dest);
+
+ if (!vlan)
+ return RX_XDP_HANDLER_FALLBACK;
+
+ dev = vlan->dev;
+ if (unlikely(!(dev->flags & IFF_UP)))
+ return RX_XDP_HANDLER_DROP;
+
+ return macvlan_receive_xdp(dev, xdp);
+}
+
/* called under rcu_read_lock() from netif_receive_skb */
static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
{
@@ -1089,6 +1206,44 @@ static int macvlan_dev_get_iflink(const struct net_device *dev)
return vlan->lowerdev->ifindex;
}
+static int macvlan_xdp_set(struct net_device *dev, struct bpf_prog *prog,
+ struct netlink_ext_ack *extack)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct bpf_prog *old_prog = rtnl_dereference(vlan->xdp_prog);
+
+ rcu_assign_pointer(vlan->xdp_prog, prog);
+
+ if (old_prog)
+ bpf_prog_put(old_prog);
+
+ return 0;
+}
+
+static u32 macvlan_xdp_query(struct net_device *dev)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ const struct bpf_prog *xdp_prog = rtnl_dereference(vlan->xdp_prog);
+
+ if (xdp_prog)
+ return xdp_prog->aux->id;
+
+ return 0;
+}
+
+static int macvlan_xdp(struct net_device *dev, struct netdev_bpf *xdp)
+{
+ switch (xdp->command) {
+ case XDP_SETUP_PROG:
+ return macvlan_xdp_set(dev, xdp->prog, xdp->extack);
+ case XDP_QUERY_PROG:
+ xdp->prog_id = macvlan_xdp_query(dev);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
static const struct ethtool_ops macvlan_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_link_ksettings = macvlan_ethtool_get_link_ksettings,
@@ -1121,6 +1276,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
#endif
.ndo_get_iflink = macvlan_dev_get_iflink,
.ndo_features_check = passthru_features_check,
+ .ndo_bpf = macvlan_xdp,
};
void macvlan_common_setup(struct net_device *dev)
@@ -1173,10 +1329,20 @@ static int macvlan_port_create(struct net_device *dev)
INIT_WORK(&port->bc_work, macvlan_process_broadcast);
err = netdev_rx_handler_register(dev, macvlan_handle_frame, port);
- if (err)
+ if (err) {
kfree(port);
- else
- dev->priv_flags |= IFF_MACVLAN_PORT;
+ goto out;
+ }
+
+ err = netdev_rx_xdp_handler_register(dev, macvlan_handle_xdp);
+ if (err) {
+ netdev_rx_handler_unregister(dev);
+ kfree(port);
+ goto out;
+ }
+
+ dev->priv_flags |= IFF_MACVLAN_PORT;
+out:
return err;
}
@@ -1187,6 +1353,7 @@ static void macvlan_port_destroy(struct net_device *dev)
dev->priv_flags &= ~IFF_MACVLAN_PORT;
netdev_rx_handler_unregister(dev);
+ netdev_rx_xdp_handler_unregister(dev);
/* After this point, no packet can schedule bc_work anymore,
* but we need to cancel it and purge left skbs if any.
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index 2e55e4c..7c7059b 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -34,6 +34,7 @@ struct macvlan_dev {
#ifdef CONFIG_NET_POLL_CONTROLLER
struct netpoll *netpoll;
#endif
+ struct bpf_prog __rcu *xdp_prog;
};
static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
--
2.7.4
^ permalink raw reply related
* [PATCH net-next] virtio_net: remove duplicated include from virtio_net.c
From: YueHaibing @ 2018-08-13 6:13 UTC (permalink / raw)
To: mst, jasowang, davem; +Cc: linux-kernel, netdev, virtualization, YueHaibing
Remove duplicated include linux/netdevice.h
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
drivers/net/virtio_net.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index eb00ae6..7659209 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -30,7 +30,6 @@
#include <linux/cpu.h>
#include <linux/average.h>
#include <linux/filter.h>
-#include <linux/netdevice.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <net/route.h>
--
2.7.0
^ permalink raw reply related
* [PATCH] net: stmmac: Add SMC support for EMAC System Manager register
From: Ooi, Joyce @ 2018-08-13 6:41 UTC (permalink / raw)
To: Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu
Cc: David S. Miller, netdev, linux-kernel, Ong Hean Loong,
Yves Vandervennet, Joyce Ooi
As there is restriction to access to EMAC System Manager registers in
the kernel for Intel Stratix10, the use of SMC calls are required and
added in dwmac-socfpga driver.
Signed-off-by: Ooi, Joyce <joyce.ooi@intel.com>
---
This patch is dependent on https://lkml.org/lkml/2018/7/26/624
---
.../net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 74 +++++++++++++++++++-
1 files changed, 73 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index c3a78c1..2cea97d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -23,6 +23,9 @@
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/stmmac.h>
+#ifdef CONFIG_HAVE_ARM_SMCCC
+#include <linux/stratix10-smc.h>
+#endif
#include "stmmac.h"
#include "stmmac_platform.h"
@@ -52,6 +55,7 @@ struct socfpga_dwmac {
int interface;
u32 reg_offset;
u32 reg_shift;
+ u32 sysmgr_reg;
struct device *dev;
struct regmap *sys_mgr_base_addr;
struct reset_control *stmmac_rst;
@@ -61,6 +65,48 @@ struct socfpga_dwmac {
struct tse_pcs pcs;
};
+#ifdef CONFIG_HAVE_ARM_SMCCC
+/**************** Stratix 10 EMAC Memory Controller Functions ************/
+
+/* s10_protected_reg_write
+ * Write to a protected SMC register.
+ * @reg: Address of register
+ * @value: Value to write
+ * Return: INTEL_SIP_SMC_STATUS_OK (0) on success
+ * INTEL_SIP_SMC_REG_ERROR on error
+ * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported
+ */
+static int s10_protected_reg_write(unsigned int reg, unsigned int val)
+{
+ struct arm_smccc_res result;
+
+ arm_smccc_smc(INTEL_SIP_SMC_REG_WRITE, reg, val, 0, 0,
+ 0, 0, 0, &result);
+
+ return (int)result.a0;
+}
+
+/* s10_protected_reg_read
+ * Read the status of a protected SMC register
+ * @reg: Address of register
+ * @value: Value read.
+ * Return: INTEL_SIP_SMC_STATUS_OK (0) on success
+ * INTEL_SIP_SMC_REG_ERROR on error
+ * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported
+ */
+static int s10_protected_reg_read(unsigned int reg, unsigned int *val)
+{
+ struct arm_smccc_res result;
+
+ arm_smccc_smc(INTEL_SIP_SMC_REG_READ, reg, 0, 0, 0,
+ 0, 0, 0, &result);
+
+ *val = (unsigned int)result.a1;
+
+ return (int)result.a0;
+}
+#endif
+
static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
{
struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv;
@@ -104,10 +150,11 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
{
struct device_node *np = dev->of_node;
struct regmap *sys_mgr_base_addr;
- u32 reg_offset, reg_shift;
+ u32 reg_offset, reg_shift, sysmgr_reg;
int ret, index;
struct device_node *np_splitter = NULL;
struct device_node *np_sgmii_adapter = NULL;
+ struct device_node *np_sysmgr = NULL;
struct resource res_splitter;
struct resource res_tse_pcs;
struct resource res_sgmii_adapter;
@@ -132,6 +179,16 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
return -EINVAL;
}
+ np_sysmgr = of_parse_phandle(np, "altr,sysmgr-syscon", 0);
+ if (np_sysmgr) {
+ ret = of_property_read_u32_index(np_sysmgr, "reg", 0,
+ &sysmgr_reg);
+ if (ret) {
+ dev_info(dev, "Could not read sysmgr register address\n");
+ return -EINVAL;
+ }
+ }
+
dwmac->f2h_ptp_ref_clk = of_property_read_bool(np, "altr,f2h_ptp_ref_clk");
np_splitter = of_parse_phandle(np, "altr,emac-splitter", 0);
@@ -221,6 +278,7 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
}
dwmac->reg_offset = reg_offset;
dwmac->reg_shift = reg_shift;
+ dwmac->sysmgr_reg = sysmgr_reg;
dwmac->sys_mgr_base_addr = sys_mgr_base_addr;
dwmac->dev = dev;
of_node_put(np_sgmii_adapter);
@@ -238,7 +296,9 @@ static int socfpga_dwmac_set_phy_mode(struct socfpga_dwmac *dwmac)
int phymode = dwmac->interface;
u32 reg_offset = dwmac->reg_offset;
u32 reg_shift = dwmac->reg_shift;
+ u32 sysmgr_reg = dwmac->sysmgr_reg;
u32 ctrl, val, module;
+ int ret = 0;
switch (phymode) {
case PHY_INTERFACE_MODE_RGMII:
@@ -266,7 +326,13 @@ static int socfpga_dwmac_set_phy_mode(struct socfpga_dwmac *dwmac)
reset_control_assert(dwmac->stmmac_ocp_rst);
reset_control_assert(dwmac->stmmac_rst);
+#ifdef CONFIG_HAVE_ARM_SMCCC
+ ret = s10_protected_reg_read(sysmgr_reg + reg_offset, &ctrl);
+ if (ret)
+ dev_err(dwmac->dev, "error reading Sys Mgr %d\n", ret);
+#else
regmap_read(sys_mgr_base_addr, reg_offset, &ctrl);
+#endif
ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
ctrl |= val << reg_shift;
@@ -281,7 +347,13 @@ static int socfpga_dwmac_set_phy_mode(struct socfpga_dwmac *dwmac)
ctrl &= ~(SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2));
}
+#ifdef CONFIG_HAVE_ARM_SMCCC
+ ret = s10_protected_reg_write(sysmgr_reg + reg_offset, ctrl);
+ if (ret)
+ dev_err(dwmac->dev, "error writing Sys Mgr %d\n", ret);
+#else
regmap_write(sys_mgr_base_addr, reg_offset, ctrl);
+#endif
/* Deassert reset for the phy configuration to be sampled by
* the enet controller, and operation to start in requested mode
--
1.7.1
^ permalink raw reply related
* [PATCH] cxgb4: remove set but not used variable 'spd'
From: YueHaibing @ 2018-08-13 6:48 UTC (permalink / raw)
To: ganeshgr, davem; +Cc: linux-kernel, netdev, YueHaibing
Fixes gcc '-Wunused-but-set-variable' warning:
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c: In function 'print_port_info':
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:5147:14: warning:
variable 'spd' set but not used [-Wunused-but-set-variable]
variable 'spd' is set but not used since
commit 547fd27241a8 ("cxgb4: Warn if device doesn't have enough PCI bandwidth")
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 69590cf..961e3087 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -5144,17 +5144,9 @@ static void print_port_info(const struct net_device *dev)
{
char buf[80];
char *bufp = buf;
- const char *spd = "";
const struct port_info *pi = netdev_priv(dev);
const struct adapter *adap = pi->adapter;
- if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_2_5GB)
- spd = " 2.5 GT/s";
- else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_5_0GB)
- spd = " 5 GT/s";
- else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_8_0GB)
- spd = " 8 GT/s";
-
if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_100M)
bufp += sprintf(bufp, "100M/");
if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_1G)
--
2.7.0
^ permalink raw reply related
* Re: [PATCH] cxgb4: remove set but not used variable 'spd'
From: YueHaibing @ 2018-08-13 6:50 UTC (permalink / raw)
To: ganeshgr, davem; +Cc: linux-kernel, netdev
In-Reply-To: <20180813064851.912-1-yuehaibing@huawei.com>
Sorry, this should be for net-next
On 2018/8/13 14:48, YueHaibing wrote:
> Fixes gcc '-Wunused-but-set-variable' warning:
> drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c: In function 'print_port_info':
> drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:5147:14: warning:
> variable 'spd' set but not used [-Wunused-but-set-variable]
>
> variable 'spd' is set but not used since
> commit 547fd27241a8 ("cxgb4: Warn if device doesn't have enough PCI bandwidth")
>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
> drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 8 --------
> 1 file changed, 8 deletions(-)
>
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> index 69590cf..961e3087 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
> @@ -5144,17 +5144,9 @@ static void print_port_info(const struct net_device *dev)
> {
> char buf[80];
> char *bufp = buf;
> - const char *spd = "";
> const struct port_info *pi = netdev_priv(dev);
> const struct adapter *adap = pi->adapter;
>
> - if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_2_5GB)
> - spd = " 2.5 GT/s";
> - else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_5_0GB)
> - spd = " 5 GT/s";
> - else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_8_0GB)
> - spd = " 8 GT/s";
> -
> if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_100M)
> bufp += sprintf(bufp, "100M/");
> if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_1G)
>
^ permalink raw reply
* [PATCH net-next] cxgb4: remove set but not used variable 'spd'
From: YueHaibing @ 2018-08-13 6:59 UTC (permalink / raw)
To: ganeshgr, davem; +Cc: linux-kernel, netdev, YueHaibing
Fixes gcc '-Wunused-but-set-variable' warning:
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c: In function 'print_port_info':
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:5147:14: warning:
variable 'spd' set but not used [-Wunused-but-set-variable]
variable 'spd' is set but not used since
commit 547fd27241a8 ("cxgb4: Warn if device doesn't have enough PCI bandwidth")
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 69590cf..961e3087 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -5144,17 +5144,9 @@ static void print_port_info(const struct net_device *dev)
{
char buf[80];
char *bufp = buf;
- const char *spd = "";
const struct port_info *pi = netdev_priv(dev);
const struct adapter *adap = pi->adapter;
- if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_2_5GB)
- spd = " 2.5 GT/s";
- else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_5_0GB)
- spd = " 5 GT/s";
- else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_8_0GB)
- spd = " 8 GT/s";
-
if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_100M)
bufp += sprintf(bufp, "100M/");
if (pi->link_cfg.pcaps & FW_PORT_CAP32_SPEED_1G)
--
2.7.0
^ permalink raw reply related
* [PATCH net-next] docs: net: Convert tcp.txt to RST format
From: Tobin C. Harding @ 2018-08-13 7:20 UTC (permalink / raw)
To: David S. Miller
Cc: Tobin C. Harding, Eric Dumazet, netdev, linux-doc, linux-kernel
Restructured text is the kernel documentation format of choice now.
Some text from tcp.txt is out of date, specifically the function
tcp_write() does not appear to be in the tree anymore. Also the
following data members have been removed
sk->tcp_pend_event
sk->transmit_queue
sk->transmit_new
sk->transmit_end
sk->tcp_last_tx_ack
sk->tcp_dup_ack
Remove section 'How the new TCP output machine [nyi] works'. This
leaves only a single section so we can name the document with that
section heading now.
Convert tcp.txt to RST format. Add GPLv2 SPDX tag.
Signed-off-by: Tobin C. Harding <me@tobin.cc>
---
CC'd Eric as maintainer of TCP (according to MAINTAINERS)
I was going to ask a question on netdev list as to whether this file was
out of date. I just removed the suspect section and did the patch
instead. I am not sure if it is correct to remove it or if the
structure documented has just been changed. Please see bottom section
of removed text ('How the new TCP output machine [nyi] works').
Also please note this file is not covered by MAINTAINERS, should it be?
thanks,
Tobin.
Documentation/networking/00-INDEX | 2 -
Documentation/networking/index.rst | 1 +
Documentation/networking/tcp.rst | 71 ++++++++++++++++++++
Documentation/networking/tcp.txt | 101 -----------------------------
4 files changed, 72 insertions(+), 103 deletions(-)
create mode 100644 Documentation/networking/tcp.rst
delete mode 100644 Documentation/networking/tcp.txt
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 02a323c43261..dcbccae4043e 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -198,8 +198,6 @@ tc-actions-env-rules.txt
- rules for traffic control (tc) actions.
timestamping.txt
- overview of network packet timestamping variants.
-tcp.txt
- - short blurb on how TCP output takes place.
tcp-thin.txt
- kernel tuning options for low rate 'thin' TCP streams.
team.txt
diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst
index fcd710f2cc7a..1cb9bcc36dd7 100644
--- a/Documentation/networking/index.rst
+++ b/Documentation/networking/index.rst
@@ -21,6 +21,7 @@ Contents:
net_failover
alias
bridge
+ tcp
.. only:: subproject
diff --git a/Documentation/networking/tcp.rst b/Documentation/networking/tcp.rst
new file mode 100644
index 000000000000..ae2094fc5de3
--- /dev/null
+++ b/Documentation/networking/tcp.rst
@@ -0,0 +1,71 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+======================
+TCP Congestion Control
+======================
+
+The following variables are used in the tcp_sock for congestion control
+
+.. flat-table:: Congestion Control
+ :widths: 1 2
+
+ * - tcp_sock struct member
+ - Usage
+
+ * - snd_cwnd
+ - The size of the congestion window
+
+ * - snd_ssthresh
+ - Slow start threshold. We are in slow start if snd_cwnd is less
+ than this.
+
+ * - snd_cwnd_cnt
+ - A counter used to slow down the rate of increase once we exceed
+ slow start threshold.
+
+ * - snd_cwnd_clamp
+ - This is the maximum size that snd_cwnd can grow to.
+
+ * - snd_cwnd_stamp
+ - Timestamp for when congestion window last validated.
+
+ * - snd_cwnd_used
+ - Used as a highwater mark for how much of the congestion window
+ is in use. It is used to adjust snd_cwnd down when the link is
+ limited by the application rather than the network.
+
+As of 2.6.13, Linux supports pluggable congestion control algorithms. A
+congestion control mechanism can be registered through functions in
+tcp_cong.c. The functions used by the congestion control mechanism are
+registered via passing a tcp_congestion_ops struct to
+tcp_register_congestion_control. As a minimum, the congestion control
+mechanism must provide a valid name and must implement either ssthresh,
+cong_avoid and undo_cwnd hooks or the "omnipotent" cong_control hook.
+
+Private data for a congestion control mechanism is stored in
+tp->ca_priv. tcp_ca(tp) returns a pointer to this space. This is
+preallocated space - it is important to check the size of your private
+data will fit this space, or alternatively, space could be allocated
+elsewhere and a pointer to it could be stored here.
+
+There are three kinds of congestion control algorithms currently: The
+simplest ones are derived from TCP reno (highspeed, scalable) and just
+provide an alternative congestion window calculation. More complex ones
+like BIC try to look at other events to provide better heuristics.
+There are also round trip time based algorithms like Vegas and
+Westwood+.
+
+Good TCP congestion control is a complex problem because the algorithm
+needs to maintain fairness and performance. Please review current
+research and RFC's before developing new modules.
+
+The default congestion control mechanism is chosen based on the
+DEFAULT_TCP_CONG Kconfig parameter. If you really want a particular
+default value then you can set it using sysctl
+net.ipv4.tcp_congestion_control. The module will be autoloaded if
+needed and you will get the expected protocol. If you ask for an
+unknown congestion method, then the sysctl attempt will fail.
+
+If you remove a TCP congestion control module, then you will get the
+next available one. Since reno cannot be built as a module, and cannot
+be removed, it will always be available.
diff --git a/Documentation/networking/tcp.txt b/Documentation/networking/tcp.txt
deleted file mode 100644
index 9c7139d57e57..000000000000
--- a/Documentation/networking/tcp.txt
+++ /dev/null
@@ -1,101 +0,0 @@
-TCP protocol
-============
-
-Last updated: 3 June 2017
-
-Contents
-========
-
-- Congestion control
-- How the new TCP output machine [nyi] works
-
-Congestion control
-==================
-
-The following variables are used in the tcp_sock for congestion control:
-snd_cwnd The size of the congestion window
-snd_ssthresh Slow start threshold. We are in slow start if
- snd_cwnd is less than this.
-snd_cwnd_cnt A counter used to slow down the rate of increase
- once we exceed slow start threshold.
-snd_cwnd_clamp This is the maximum size that snd_cwnd can grow to.
-snd_cwnd_stamp Timestamp for when congestion window last validated.
-snd_cwnd_used Used as a highwater mark for how much of the
- congestion window is in use. It is used to adjust
- snd_cwnd down when the link is limited by the
- application rather than the network.
-
-As of 2.6.13, Linux supports pluggable congestion control algorithms.
-A congestion control mechanism can be registered through functions in
-tcp_cong.c. The functions used by the congestion control mechanism are
-registered via passing a tcp_congestion_ops struct to
-tcp_register_congestion_control. As a minimum, the congestion control
-mechanism must provide a valid name and must implement either ssthresh,
-cong_avoid and undo_cwnd hooks or the "omnipotent" cong_control hook.
-
-Private data for a congestion control mechanism is stored in tp->ca_priv.
-tcp_ca(tp) returns a pointer to this space. This is preallocated space - it
-is important to check the size of your private data will fit this space, or
-alternatively, space could be allocated elsewhere and a pointer to it could
-be stored here.
-
-There are three kinds of congestion control algorithms currently: The
-simplest ones are derived from TCP reno (highspeed, scalable) and just
-provide an alternative congestion window calculation. More complex
-ones like BIC try to look at other events to provide better
-heuristics. There are also round trip time based algorithms like
-Vegas and Westwood+.
-
-Good TCP congestion control is a complex problem because the algorithm
-needs to maintain fairness and performance. Please review current
-research and RFC's before developing new modules.
-
-The default congestion control mechanism is chosen based on the
-DEFAULT_TCP_CONG Kconfig parameter. If you really want a particular default
-value then you can set it using sysctl net.ipv4.tcp_congestion_control. The
-module will be autoloaded if needed and you will get the expected protocol. If
-you ask for an unknown congestion method, then the sysctl attempt will fail.
-
-If you remove a TCP congestion control module, then you will get the next
-available one. Since reno cannot be built as a module, and cannot be
-removed, it will always be available.
-
-How the new TCP output machine [nyi] works.
-===========================================
-
-Data is kept on a single queue. The skb->users flag tells us if the frame is
-one that has been queued already. To add a frame we throw it on the end. Ack
-walks down the list from the start.
-
-We keep a set of control flags
-
-
- sk->tcp_pend_event
-
- TCP_PEND_ACK Ack needed
- TCP_ACK_NOW Needed now
- TCP_WINDOW Window update check
- TCP_WINZERO Zero probing
-
-
- sk->transmit_queue The transmission frame begin
- sk->transmit_new First new frame pointer
- sk->transmit_end Where to add frames
-
- sk->tcp_last_tx_ack Last ack seen
- sk->tcp_dup_ack Dup ack count for fast retransmit
-
-
-Frames are queued for output by tcp_write. We do our best to send the frames
-off immediately if possible, but otherwise queue and compute the body
-checksum in the copy.
-
-When a write is done we try to clear any pending events and piggy back them.
-If the window is full we queue full sized frames. On the first timeout in
-zero window we split this.
-
-On a timer we walk the retransmit list to send any retransmits, update the
-backoff timers etc. A change of route table stamp causes a change of header
-and recompute. We add any new tcp level headers and refinish the checksum
-before sending.
-
--
2.17.1
^ permalink raw reply related
* [PATCH net-next] liquidio: remove set but not used variable 'is25G'
From: YueHaibing @ 2018-08-13 7:21 UTC (permalink / raw)
To: davem, derek.chickles, satananda.burla, felix.manlunas,
raghu.vatsavayi
Cc: linux-kernel, netdev, YueHaibing
Fixes gcc '-Wunused-but-set-variable' warning:
drivers/net/ethernet/cavium/liquidio/lio_ethtool.c: In function 'lio_set_link_ksettings':
drivers/net/ethernet/cavium/liquidio/lio_ethtool.c:392:6: warning:
variable 'is25G' set but not used [-Wunused-but-set-variable]
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
drivers/net/ethernet/cavium/liquidio/lio_ethtool.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
index 807ea2c..5ce604a 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
@@ -389,16 +389,13 @@ static int lio_set_link_ksettings(struct net_device *netdev,
struct lio *lio = GET_LIO(netdev);
struct oct_link_info *linfo;
struct octeon_device *oct;
- u32 is25G = 0;
oct = lio->oct_dev;
linfo = &lio->linfo;
- if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
- oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) {
- is25G = 1;
- } else {
+ if (!(oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
+ oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID)) {
return -EOPNOTSUPP;
}
--
2.7.0
^ permalink raw reply related
* Re: [PATCH net-next] cxgb4: remove set but not used variable 'spd'
From: Ganesh Goudar @ 2018-08-13 7:36 UTC (permalink / raw)
To: YueHaibing, davem; +Cc: linux-kernel, netdev, dt
In-Reply-To: <20180813065902.5504-1-yuehaibing@huawei.com>
On Monday, August 08/13/18, 2018 at 14:59:02 +0800, YueHaibing wrote:
> Fixes gcc '-Wunused-but-set-variable' warning:
> drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c: In function 'print_port_info':
> drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:5147:14: warning:
> variable 'spd' set but not used [-Wunused-but-set-variable]
>
> variable 'spd' is set but not used since
> commit 547fd27241a8 ("cxgb4: Warn if device doesn't have enough PCI bandwidth")
>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
> drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 8 --------
> 1 file changed, 8 deletions(-)
>
Thanks, YueHaibing.
Acked-by: Ganesh Goudar <ganeshgr@chelsio.com>
^ permalink raw reply
* [PATCH net-next] lan743x: lan743x: Remove duplicated include from lan743x_ptp.c
From: Yue Haibing @ 2018-08-13 6:39 UTC (permalink / raw)
To: Bryan Whitehead, Microchip Linux Driver Support, David S. Miller
Cc: Yue Haibing, netdev, kernel-janitors
Remove duplicated include.
Signed-off-by: Yue Haibing <yuehaibing@huawei.com>
---
drivers/net/ethernet/microchip/lan743x_ptp.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.c b/drivers/net/ethernet/microchip/lan743x_ptp.c
index 42064fd..029a2af 100644
--- a/drivers/net/ethernet/microchip/lan743x_ptp.c
+++ b/drivers/net/ethernet/microchip/lan743x_ptp.c
@@ -6,7 +6,6 @@
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/netdevice.h>
#include <linux/net_tstamp.h>
#include "lan743x_ptp.h"
^ permalink raw reply related
* Re: [PATCH net-next] liquidio: remove set but not used variable 'is25G'
From: YueHaibing @ 2018-08-13 9:24 UTC (permalink / raw)
To: Shaikh, Shahed, davem@davemloft.net, Chickles, Derek,
Burla, Satananda, Manlunas, Felix, Vatsavayi, Raghu
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org
In-Reply-To: <BY2PR07MB245416297A60474BA77A99A39D390@BY2PR07MB2454.namprd07.prod.outlook.com>
On 2018/8/13 17:08, Shaikh, Shahed wrote:
>> -----Original Message-----
>> From: netdev-owner@vger.kernel.org <netdev-owner@vger.kernel.org> On
>> Behalf Of YueHaibing
>> Sent: Monday, August 13, 2018 12:51 PM
>> To: davem@davemloft.net; Chickles, Derek <Derek.Chickles@cavium.com>;
>> Burla, Satananda <Satananda.Burla@cavium.com>; Manlunas, Felix
>> <Felix.Manlunas@cavium.com>; Vatsavayi, Raghu
>> <Raghu.Vatsavayi@cavium.com>
>> Cc: linux-kernel@vger.kernel.org; netdev@vger.kernel.org; YueHaibing
>> <yuehaibing@huawei.com>
>> Subject: [PATCH net-next] liquidio: remove set but not used variable 'is25G'
>>
>> External Email
>>
>> Fixes gcc '-Wunused-but-set-variable' warning:
>>
>> drivers/net/ethernet/cavium/liquidio/lio_ethtool.c: In function
>> 'lio_set_link_ksettings':
>> drivers/net/ethernet/cavium/liquidio/lio_ethtool.c:392:6: warning:
>> variable 'is25G' set but not used [-Wunused-but-set-variable]
>>
>> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
>> ---
>> drivers/net/ethernet/cavium/liquidio/lio_ethtool.c | 7 ++-----
>> 1 file changed, 2 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
>> b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
>> index 807ea2c..5ce604a 100644
>> --- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
>> +++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
>> @@ -389,16 +389,13 @@ static int lio_set_link_ksettings(struct net_device
>> *netdev,
>> struct lio *lio = GET_LIO(netdev);
>> struct oct_link_info *linfo;
>> struct octeon_device *oct;
>> - u32 is25G = 0;
>>
>> oct = lio->oct_dev;
>>
>> linfo = &lio->linfo;
>>
>> - if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
>> - oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) {
>> - is25G = 1;
>> - } else {
>> + if (!(oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
>> + oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID)) {
>> return -EOPNOTSUPP;
>> }
>
> You can also remove braces which are not required for single line.
Yes, thanks. Will post v2
> Thanks,
> Shahed
>
>
>
^ permalink raw reply
* [PATCH v2 net-next] liquidio: remove set but not used variable 'is25G'
From: YueHaibing @ 2018-08-13 9:29 UTC (permalink / raw)
To: davem, derek.chickles, satananda.burla, felix.manlunas,
raghu.vatsavayi
Cc: linux-kernel, netdev, YueHaibing
Fixes gcc '-Wunused-but-set-variable' warning:
drivers/net/ethernet/cavium/liquidio/lio_ethtool.c: In function 'lio_set_link_ksettings':
drivers/net/ethernet/cavium/liquidio/lio_ethtool.c:392:6: warning:
variable 'is25G' set but not used [-Wunused-but-set-variable]
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
v2: remove unnecessary braces as Shahed suggested
---
drivers/net/ethernet/cavium/liquidio/lio_ethtool.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
index 807ea2c..8e05afd 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
@@ -389,18 +389,14 @@ static int lio_set_link_ksettings(struct net_device *netdev,
struct lio *lio = GET_LIO(netdev);
struct oct_link_info *linfo;
struct octeon_device *oct;
- u32 is25G = 0;
oct = lio->oct_dev;
linfo = &lio->linfo;
- if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
- oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) {
- is25G = 1;
- } else {
+ if (!(oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
+ oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID))
return -EOPNOTSUPP;
- }
if (oct->no_speed_setting) {
dev_err(&oct->pci_dev->dev, "%s: Changing speed is not supported\n",
--
2.7.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox