Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,10 @@ struct netdev_queue {
* (/sys/class/net/DEV/Q/trans_timeout)
*/
unsigned long trans_timeout;

#ifdef CONFIG_XDP_SOCKETS
struct xdp_umem *umem;
#endif
/*
* write-mostly part
*/
Expand Down Expand Up @@ -706,6 +710,9 @@ struct netdev_rx_queue {
struct kobject kobj;
struct net_device *dev;
struct xdp_rxq_info xdp_rxq;
#ifdef CONFIG_XDP_SOCKETS
struct xdp_umem *umem;
#endif
} ____cacheline_aligned_in_smp;

/*
Expand Down Expand Up @@ -2572,6 +2579,7 @@ void dev_disable_lro(struct net_device *dev);
int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *newskb);
int dev_queue_xmit(struct sk_buff *skb);
int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv);
int dev_direct_xmit(struct sk_buff *skb, u16 queue_id);
int register_netdevice(struct net_device *dev);
void unregister_netdevice_queue(struct net_device *dev, struct list_head *head);
void unregister_netdevice_many(struct list_head *head);
Expand Down Expand Up @@ -2930,6 +2938,9 @@ struct softnet_data {
struct Qdisc *output_queue;
struct Qdisc **output_queue_tailp;
struct sk_buff *completion_queue;
#ifdef CONFIG_XFRM_OFFLOAD
struct sk_buff_head xfrm_backlog;
#endif
/* written and read only by owning cpu: */
struct {
u16 recursion;
Expand Down Expand Up @@ -3495,7 +3506,7 @@ int dev_get_phys_port_name(struct net_device *dev,
char *name, size_t len);
int dev_change_proto_down(struct net_device *dev, bool proto_down);
int dev_change_proto_down_generic(struct net_device *dev, bool proto_down);
struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev);
struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev, bool *again);
struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
struct netdev_queue *txq, int *ret);

Expand Down
24 changes: 20 additions & 4 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,7 @@ struct xfrm_offload {
#define XFRM_GSO_SEGMENT 16
#define XFRM_GRO 32
#define XFRM_ESP_NO_TRAILER 64
#define XFRM_DEV_RESUME 128

__u32 status;
#define CRYPTO_SUCCESS 1
Expand Down Expand Up @@ -1920,21 +1921,28 @@ static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb)
{
return skb->sp->xvec[skb->sp->len - 1];
}
#endif

static inline struct xfrm_offload *xfrm_offload(struct sk_buff *skb)
{
#ifdef CONFIG_XFRM
struct sec_path *sp = skb->sp;

if (!sp || !sp->olen || sp->len != sp->olen)
return NULL;

return &sp->ovec[sp->olen - 1];
}
#else
return NULL;
#endif
}

void __net_init xfrm_dev_init(void);

#ifdef CONFIG_XFRM_OFFLOAD
int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features);
void xfrm_dev_resume(struct sk_buff *skb);
void xfrm_dev_backlog(struct softnet_data *sd);
struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again);
int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
struct xfrm_user_offload *xuo);
bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x);
Expand Down Expand Up @@ -1975,9 +1983,17 @@ static inline void xfrm_dev_state_free(struct xfrm_state *x)
}
}
#else
static inline int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features)
static inline void xfrm_dev_resume(struct sk_buff *skb)
{
return 0;
}

static inline void xfrm_dev_backlog(struct softnet_data *sd)
{
}

static inline struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again)
{
return skb;
}

static inline int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, struct xfrm_user_offload *xuo)
Expand Down
57 changes: 50 additions & 7 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -3260,7 +3260,7 @@ int skb_csum_hwoffload_help(struct sk_buff *skb,
}
EXPORT_SYMBOL(skb_csum_hwoffload_help);

static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device *dev, bool *again)
{
netdev_features_t features;

Expand All @@ -3284,9 +3284,6 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
__skb_linearize(skb))
goto out_kfree_skb;

if (validate_xmit_xfrm(skb, features))
goto out_kfree_skb;

/* If packet is not checksummed and device does not
* support checksumming for this protocol, complete
* checksumming here.
Expand All @@ -3303,6 +3300,8 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
}
}

skb = validate_xmit_xfrm(skb, features, again);

return skb;

out_kfree_skb:
Expand All @@ -3312,7 +3311,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
return NULL;
}

struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev)
struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev, bool *again)
{
struct sk_buff *next, *head = NULL, *tail;

Expand All @@ -3323,7 +3322,7 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d
/* in case skb wont be segmented, point to itself */
skb->prev = skb;

skb = validate_xmit_skb(skb, dev);
skb = validate_xmit_skb(skb, dev, again);
if (!skb)
continue;

Expand Down Expand Up @@ -3654,6 +3653,7 @@ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
struct netdev_queue *txq;
struct Qdisc *q;
int rc = -ENOMEM;
bool again = false;

skb_reset_mac_header(skb);
skb_assert_len(skb);
Expand Down Expand Up @@ -3715,7 +3715,7 @@ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
if (dev_xmit_recursion())
goto recursion_alert;

skb = validate_xmit_skb(skb, dev);
skb = validate_xmit_skb(skb, dev, &again);
if (!skb)
goto out;

Expand Down Expand Up @@ -3766,6 +3766,44 @@ int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv)
}
EXPORT_SYMBOL(dev_queue_xmit_accel);

int dev_direct_xmit(struct sk_buff *skb, u16 queue_id)
{
struct net_device *dev = skb->dev;
struct sk_buff *orig_skb = skb;
struct netdev_queue *txq;
int ret = NETDEV_TX_BUSY;
bool again = false;

if (unlikely(!netif_running(dev) ||
!netif_carrier_ok(dev)))
goto drop;

skb = validate_xmit_skb_list(skb, dev, &again);
if (skb != orig_skb)
goto drop;

skb_set_queue_mapping(skb, queue_id);
txq = skb_get_tx_queue(dev, skb);

local_bh_disable();

HARD_TX_LOCK(dev, txq, smp_processor_id());
if (!netif_xmit_frozen_or_drv_stopped(txq))
ret = netdev_start_xmit(skb, dev, txq, false);
HARD_TX_UNLOCK(dev, txq);

local_bh_enable();

if (!dev_xmit_complete(ret))
kfree_skb(skb);

return ret;
drop:
atomic_long_inc(&dev->tx_dropped);
kfree_skb_list(skb);
return NET_XMIT_DROP;
}
EXPORT_SYMBOL(dev_direct_xmit);

/*************************************************************************
* Receiver routines
Expand Down Expand Up @@ -4438,6 +4476,8 @@ static __latent_entropy void net_tx_action(struct softirq_action *h)
spin_unlock(root_lock);
}
}

xfrm_dev_backlog(sd);
}

#if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_ATM_LANE)
Expand Down Expand Up @@ -9555,6 +9595,9 @@ static int __init net_dev_init(void)

skb_queue_head_init(&sd->input_pkt_queue);
skb_queue_head_init(&sd->process_queue);
#ifdef CONFIG_XFRM_OFFLOAD
skb_queue_head_init(&sd->xfrm_backlog);
#endif
INIT_LIST_HEAD(&sd->poll_list);
sd->output_queue_tailp = &sd->output_queue;
#ifdef CONFIG_RPS
Expand Down
24 changes: 21 additions & 3 deletions net/ipv4/esp4.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,32 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
static void esp_output_done(struct crypto_async_request *base, int err)
{
struct sk_buff *skb = base->data;
struct xfrm_offload *xo = xfrm_offload(skb);
void *tmp;
struct dst_entry *dst = skb_dst(skb);
struct xfrm_state *x = dst->xfrm;
struct xfrm_state *x;

if (xo && (xo->flags & XFRM_DEV_RESUME))
x = skb->sp->xvec[skb->sp->len - 1];
else
x = skb_dst(skb)->xfrm;

tmp = ESP_SKB_CB(skb)->tmp;
esp_ssg_unref(x, tmp);
kfree(tmp);
xfrm_output_resume(skb, err);

if (xo && (xo->flags & XFRM_DEV_RESUME)) {
if (err) {
XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTSTATEPROTOERROR);
kfree_skb(skb);
return;
}

skb_push(skb, skb->data - skb_mac_header(skb));
secpath_reset(skb);
xfrm_dev_resume(skb);
} else {
xfrm_output_resume(skb, err);
}
}

/* Move ESP header back into place. */
Expand Down
Loading