summaryrefslogtreecommitdiff
path: root/net/core/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c158
1 files changed, 95 insertions, 63 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 8bfa8313ef62..ece6700536d9 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1593,7 +1593,7 @@ EXPORT_SYMBOL(netdev_features_change);
void netif_state_change(struct net_device *dev)
{
- netdev_ops_assert_locked_or_invisible(dev);
+ netdev_assert_locked_ops_compat_or_invisible(dev);
if (dev->flags & IFF_UP) {
struct netdev_notifier_change_info change_info = {
@@ -1693,7 +1693,7 @@ static int __dev_open(struct net_device *dev, struct netlink_ext_ack *extack)
set_bit(__LINK_STATE_START, &dev->state);
- netdev_ops_assert_locked(dev);
+ netdev_assert_locked_ops_compat(dev);
if (ops->ndo_validate_addr)
ret = ops->ndo_validate_addr(dev);
@@ -1770,11 +1770,12 @@ static void __dev_close_many(struct list_head *head)
* event.
*/
- netdev_ops_assert_locked(dev);
+ netdev_assert_locked_ops_compat(dev);
if (ops->ndo_stop)
ops->ndo_stop(dev);
+ netif_rx_mode_cancel_retry(dev);
netif_set_up(dev, false);
netpoll_poll_enable(dev);
}
@@ -3198,7 +3199,7 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
if (dev->reg_state == NETREG_REGISTERED ||
dev->reg_state == NETREG_UNREGISTERING) {
- netdev_ops_assert_locked(dev);
+ netdev_assert_locked_ops_compat(dev);
rc = netdev_queue_update_kobjects(dev, dev->real_num_tx_queues,
txq);
@@ -3247,7 +3248,7 @@ int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq)
return -EINVAL;
if (dev->reg_state == NETREG_REGISTERED) {
- netdev_ops_assert_locked(dev);
+ netdev_assert_locked_ops_compat(dev);
rc = net_rx_queue_update_kobjects(dev, dev->real_num_rx_queues,
rxq);
@@ -3993,10 +3994,11 @@ static struct sk_buff *validate_xmit_unreadable_skb(struct sk_buff *skb,
struct skb_shared_info *shinfo;
struct net_iov *niov;
- if (likely(skb_frags_readable(skb)))
+ if (likely(skb_frags_readable(skb) ||
+ dev->netmem_tx == NETMEM_TX_NO_DMA))
goto out;
- if (!dev->netmem_tx)
+ if (dev->netmem_tx == NETMEM_TX_NONE)
goto out_free;
shinfo = skb_shinfo(skb);
@@ -4016,6 +4018,9 @@ out_free:
return NULL;
}
+/* Returns the skb on success, NULL if dropped, or ERR_PTR(-EINPROGRESS)
+ * if stolen by async xfrm crypto (delivered via xfrm_dev_resume()).
+ */
static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device *dev, bool *again)
{
netdev_features_t features;
@@ -4087,7 +4092,7 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d
skb->prev = skb;
skb = validate_xmit_skb(skb, dev, again);
- if (!skb)
+ if (IS_ERR_OR_NULL(skb))
continue;
if (!head)
@@ -4858,8 +4863,11 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev)
goto recursion_alert;
skb = validate_xmit_skb(skb, dev, &again);
- if (!skb)
+ if (IS_ERR_OR_NULL(skb)) {
+ if (PTR_ERR(skb) == -EINPROGRESS)
+ rc = NET_XMIT_SUCCESS;
goto out;
+ }
HARD_TX_LOCK(dev, txq, cpu);
@@ -5381,8 +5389,6 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
u32 tail;
reason = SKB_DROP_REASON_DEV_READY;
- if (unlikely(!netif_running(skb->dev)))
- goto bad_dev;
sd = &per_cpu(softnet_data, cpu);
@@ -5394,6 +5400,10 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
backlog_lock_irq_save(sd, &flags);
qlen = skb_queue_len(&sd->input_pkt_queue);
if (likely(qlen <= max_backlog)) {
+ if (unlikely(!netif_running(skb->dev))) {
+ backlog_unlock_irq_restore(sd, flags);
+ goto bad_dev;
+ }
if (!qlen) {
/* Schedule NAPI for backlog device. We can use
* non atomic operation as we own the queue lock.
@@ -5507,12 +5517,16 @@ u32 bpf_prog_run_generic_xdp(struct sk_buff *skb, struct xdp_buff *xdp,
}
/* XDP frag metadata (e.g. nr_frags) are updated in eBPF helpers
- * (e.g. bpf_xdp_adjust_tail), we need to update data_len here.
+ * (e.g. bpf_xdp_adjust_tail). Remove the old fragment contribution
+ * from skb->len before updating data_len, then add the new one back.
*/
- if (xdp_buff_has_frags(xdp))
+ skb->len -= skb->data_len;
+ if (xdp_buff_has_frags(xdp)) {
skb->data_len = skb_shinfo(skb)->xdp_frags_size;
- else
+ skb->len += skb->data_len;
+ } else {
skb->data_len = 0;
+ }
/* check if XDP changed eth hdr such SKB needs update */
eth = (struct ethhdr *)xdp->data;
@@ -6862,20 +6876,6 @@ static void skb_defer_free_flush(void)
#if defined(CONFIG_NET_RX_BUSY_POLL)
-static void __busy_poll_stop(struct napi_struct *napi, bool skip_schedule)
-{
- if (!skip_schedule) {
- gro_normal_list(&napi->gro);
- __napi_schedule(napi);
- return;
- }
-
- /* Flush too old packets. If HZ < 1000, flush all packets */
- gro_flush_normal(&napi->gro, HZ >= 1000);
-
- clear_bit(NAPI_STATE_SCHED, &napi->state);
-}
-
enum {
NAPI_F_PREFER_BUSY_POLL = 1,
NAPI_F_END_ON_RESCHED = 2,
@@ -6885,15 +6885,14 @@ static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock,
unsigned flags, u16 budget)
{
struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
- bool skip_schedule = false;
- unsigned long timeout;
+ unsigned long timeout = 0;
int rc;
/* Busy polling means there is a high chance device driver hard irq
* could not grab NAPI_STATE_SCHED, and that NAPI_STATE_MISSED was
* set in napi_schedule_prep().
- * Since we are about to call napi->poll() once more, we can safely
- * clear NAPI_STATE_MISSED.
+ * Since we either call napi->poll() once more or start the timer,
+ * we can safely clear NAPI_STATE_MISSED.
*
* Note: x86 could use a single "lock and ..." instruction
* to perform these two clear_bit()
@@ -6906,25 +6905,35 @@ static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock,
if (flags & NAPI_F_PREFER_BUSY_POLL) {
napi->defer_hard_irqs_count = napi_get_defer_hard_irqs(napi);
- timeout = napi_get_gro_flush_timeout(napi);
- if (napi->defer_hard_irqs_count && timeout) {
- hrtimer_start(&napi->timer, ns_to_ktime(timeout), HRTIMER_MODE_REL_PINNED);
- skip_schedule = true;
+ if (napi->defer_hard_irqs_count)
+ timeout = napi_get_gro_flush_timeout(napi);
+ }
+ if (timeout) {
+ netpoll_poll_unlock(have_poll_lock);
+
+ /* Drain aged GRO packets before clearing SCHED since the NAPI
+ * won't run again until after the timer fires. When HZ < 1000,
+ * GRO age comparison is too coarse, so flush everything.
+ */
+ gro_flush_normal(&napi->gro, HZ >= 1000);
+
+ clear_bit(NAPI_STATE_SCHED, &napi->state);
+ hrtimer_start(&napi->timer, ns_to_ktime(timeout),
+ HRTIMER_MODE_REL_PINNED);
+ } else {
+ /* Use driver poll to re-enable device interrupts. */
+ rc = napi->poll(napi, budget);
+ /* Unless rc == budget we no longer own the NAPI instance,
+ * IRQ may fire on another CPU, poll this NAPI, and enter GRO.
+ */
+ trace_napi_poll(napi, rc, budget);
+ netpoll_poll_unlock(have_poll_lock);
+ if (rc == budget) {
+ gro_normal_list(&napi->gro);
+ __napi_schedule(napi);
}
}
- /* All we really want here is to re-enable device interrupts.
- * Ideally, a new ndo_busy_poll_stop() could avoid another round.
- */
- rc = napi->poll(napi, budget);
- /* We can't gro_normal_list() here, because napi->poll() might have
- * rearmed the napi (napi_complete_done()) in which case it could
- * already be running on another CPU.
- */
- trace_napi_poll(napi, rc, budget);
- netpoll_poll_unlock(have_poll_lock);
- if (rc == budget)
- __busy_poll_stop(napi, skip_schedule);
bpf_net_ctx_clear(bpf_net_ctx);
local_bh_enable();
}
@@ -7298,7 +7307,7 @@ void netif_queue_set_napi(struct net_device *dev, unsigned int queue_index,
if (WARN_ON_ONCE(napi && !napi->dev))
return;
- netdev_ops_assert_locked_or_invisible(dev);
+ netdev_assert_locked_ops_compat_or_invisible(dev);
switch (type) {
case NETDEV_QUEUE_TYPE_RX:
@@ -9593,7 +9602,7 @@ int __dev_set_promiscuity(struct net_device *dev, int inc, bool notify)
kuid_t uid;
kgid_t gid;
- netdev_ops_assert_locked(dev);
+ netdev_assert_locked_ops_compat(dev);
promiscuity = dev->promiscuity + inc;
if (promiscuity == 0) {
@@ -9652,7 +9661,7 @@ int netif_set_allmulti(struct net_device *dev, int inc, bool notify)
unsigned int old_flags = dev->flags, old_gflags = dev->gflags;
unsigned int allmulti, flags;
- netdev_ops_assert_locked(dev);
+ netdev_assert_locked_ops_compat(dev);
allmulti = dev->allmulti + inc;
if (allmulti == 0) {
@@ -9720,7 +9729,7 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags,
unsigned int old_flags = dev->flags;
int ret;
- netdev_ops_assert_locked(dev);
+ netdev_assert_locked_ops_compat(dev);
/*
* Set the flags on our device.
@@ -9823,6 +9832,7 @@ int netif_change_flags(struct net_device *dev, unsigned int flags,
__dev_notify_flags(dev, old_flags, changes, 0, NULL);
return ret;
}
+EXPORT_SYMBOL(netif_change_flags);
int __netif_set_mtu(struct net_device *dev, int new_mtu)
{
@@ -9868,7 +9878,7 @@ int netif_set_mtu_ext(struct net_device *dev, int new_mtu,
{
int err, orig_mtu;
- netdev_ops_assert_locked(dev);
+ netdev_assert_locked_ops_compat(dev);
if (new_mtu == dev->mtu)
return 0;
@@ -10141,17 +10151,36 @@ bool netdev_port_same_parent_id(struct net_device *a, struct net_device *b)
}
EXPORT_SYMBOL(netdev_port_same_parent_id);
+static struct net_device *dev_get_iflink_dev(struct net_device *dev)
+{
+ struct net *net;
+
+ ASSERT_RTNL();
+
+ if (!dev->netdev_ops->ndo_get_iflink || !dev->rtnl_link_ops ||
+ !dev->rtnl_link_ops->get_link_net)
+ return dev;
+
+ net = dev->rtnl_link_ops->get_link_net(dev);
+ return __dev_get_by_index(net, dev_get_iflink(dev));
+}
+
int netif_change_proto_down(struct net_device *dev, bool proto_down)
{
+ struct net_device *iflink_dev;
+
if (!dev->change_proto_down)
return -EOPNOTSUPP;
if (!netif_device_present(dev))
return -ENODEV;
+ iflink_dev = dev_get_iflink_dev(dev);
+ if (!iflink_dev)
+ return -ENODEV;
+ WRITE_ONCE(dev->proto_down, proto_down);
if (proto_down)
netif_carrier_off(dev);
- else
+ else if (dev == iflink_dev || netif_carrier_ok(iflink_dev))
netif_carrier_on(dev);
- WRITE_ONCE(dev->proto_down, proto_down);
return 0;
}
@@ -10302,7 +10331,7 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode,
struct netdev_bpf xdp;
int err;
- netdev_ops_assert_locked(dev);
+ netdev_assert_locked_ops_compat(dev);
if (dev->cfg->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
prog && !prog->aux->xdp_has_frags) {
@@ -10754,7 +10783,7 @@ u32 dev_get_min_mp_channel_count(const struct net_device *dev)
{
int i;
- netdev_ops_assert_locked(dev);
+ netdev_assert_locked_ops_compat(dev);
for (i = dev->real_num_rx_queues - 1; i >= 0; i--)
if (dev->_rx[i].mp_params.mp_priv)
@@ -10982,7 +11011,7 @@ int __netdev_update_features(struct net_device *dev)
int err = -1;
ASSERT_RTNL();
- netdev_ops_assert_locked(dev);
+ netdev_assert_locked_ops_compat(dev);
features = netdev_get_wanted_features(dev);
@@ -11214,7 +11243,8 @@ static int netif_alloc_netdev_queues(struct net_device *dev)
netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL);
spin_lock_init(&dev->tx_global_lock);
-
+ spin_lock_init(&dev->watchdog_lock);
+ dev->watchdog_ref_held = false;
return 0;
}
@@ -11468,6 +11498,7 @@ int register_netdevice(struct net_device *dev)
* Prevent userspace races by waiting until the network
* device is fully setup before sending notifications.
*/
+ netdev_uevent_add(dev);
if (!(dev->rtnl_link_ops && dev->rtnl_link_initializing))
rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U, GFP_KERNEL, 0, NULL);
@@ -11715,6 +11746,8 @@ void netdev_run_todo(void)
WARN_ON(rcu_access_pointer(dev->ip_ptr));
WARN_ON(rcu_access_pointer(dev->ip6_ptr));
+ netdev_name_node_alt_flush(dev);
+ netdev_name_node_free(dev->name_node);
netdev_do_free_pcpu_stats(dev);
if (dev->priv_destructor)
dev->priv_destructor(dev);
@@ -12072,13 +12105,13 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
INIT_LIST_HEAD(&dev->ptype_all);
INIT_LIST_HEAD(&dev->ptype_specific);
INIT_LIST_HEAD(&dev->net_notifier_list);
+ INIT_LIST_HEAD(&dev->work_node);
#ifdef CONFIG_NET_SCHED
hash_init(dev->qdisc_hash);
#endif
mutex_init(&dev->lock);
- INIT_LIST_HEAD(&dev->rx_mode_node);
- __hw_addr_init(&dev->rx_mode_addr_cache);
+ netif_rx_mode_init(dev);
dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM;
setup(dev);
@@ -12407,6 +12440,7 @@ void unregister_netdevice_many_notify(struct list_head *head,
dev_tcx_uninstall(dev);
dev_xdp_uninstall(dev);
dev_memory_provider_uninstall(dev);
+ netdev_work_cancel_all(dev);
netdev_unlock_ops(dev);
bpf_dev_bound_netdev_unregister(dev);
@@ -12428,8 +12462,6 @@ void unregister_netdevice_many_notify(struct list_head *head,
dev_uc_flush(dev);
dev_mc_flush(dev);
- netdev_name_node_alt_flush(dev);
- netdev_name_node_free(dev->name_node);
netdev_rss_contexts_free(dev);