mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 10:04:12 +08:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: "Several smallish fixes, I don't think any of this requires another -rc but I'll leave that up to you: 1) Don't leak uninitialzed bytes to userspace in xfrm_user, from Eric Dumazet. 2) Route leak in xfrm_lookup_route(), from Tommi Rantala. 3) Premature poll() returns in AF_XDP, from Björn Töpel. 4) devlink leak in netdevsim, from Jakub Kicinski. 5) Don't BUG_ON in fib_compute_spec_dst, the condition can legitimately happen. From Lorenzo Bianconi. 6) Fix some spectre v1 gadgets in generic socket code, from Jeremy Cline. 7) Don't allow user to bind to out of range multicast groups, from Dmitry Safonov with a follow-up by Dmitry Safonov. 8) Fix metrics leak in fib6_drop_pcpu_from(), from Sabrina Dubroca" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (41 commits) netlink: Don't shift with UB on nlk->ngroups net/ipv6: fix metrics leak xen-netfront: wait xenbus state change when load module manually can: ems_usb: Fix memory leak on ems_usb_disconnect() openvswitch: meter: Fix setting meter id for new entries netlink: Do not subscribe to non-existent groups NET: stmmac: align DMA stuff to largest cache line length tcp_bbr: fix bw probing to raise in-flight data for very small BDPs net: socket: Fix potential spectre v1 gadget in sock_is_registered net: socket: fix potential spectre v1 gadget in socketcall net: mdio-mux: bcm-iproc: fix wrong getter and setter pair ipv4: remove BUG_ON() from fib_compute_spec_dst enic: handle mtu change for vf properly net: lan78xx: fix rx handling before first packet is send nfp: flower: fix port metadata conversion bug bpf: use GFP_ATOMIC instead of GFP_KERNEL in bpf_parse_prog() bpf: fix bpf_skb_load_bytes_relative pkt length check perf build: Build error in libbpf missing initialization net: ena: Fix use of uninitialized DMA address bits field bpf: btf: Use exact btf value_size match in map_check_btf() ...
This commit is contained in:
commit
f67077deb4
@ -1441,8 +1441,8 @@ static void emit_prologue(u8 **pprog, u32 stack_depth)
|
||||
|
||||
/* sub esp,STACK_SIZE */
|
||||
EMIT2_off32(0x81, 0xEC, STACK_SIZE);
|
||||
/* sub ebp,SCRATCH_SIZE+4+12*/
|
||||
EMIT3(0x83, add_1reg(0xE8, IA32_EBP), SCRATCH_SIZE + 16);
|
||||
/* sub ebp,SCRATCH_SIZE+12*/
|
||||
EMIT3(0x83, add_1reg(0xE8, IA32_EBP), SCRATCH_SIZE + 12);
|
||||
/* xor ebx,ebx */
|
||||
EMIT2(0x31, add_2reg(0xC0, IA32_EBX, IA32_EBX));
|
||||
|
||||
@ -1475,8 +1475,8 @@ static void emit_epilogue(u8 **pprog, u32 stack_depth)
|
||||
/* mov edx,dword ptr [ebp+off]*/
|
||||
EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EDX), STACK_VAR(r0[1]));
|
||||
|
||||
/* add ebp,SCRATCH_SIZE+4+12*/
|
||||
EMIT3(0x83, add_1reg(0xC0, IA32_EBP), SCRATCH_SIZE + 16);
|
||||
/* add ebp,SCRATCH_SIZE+12*/
|
||||
EMIT3(0x83, add_1reg(0xC0, IA32_EBP), SCRATCH_SIZE + 12);
|
||||
|
||||
/* mov ebx,dword ptr [ebp-12]*/
|
||||
EMIT3(0x8B, add_2reg(0x40, IA32_EBP, IA32_EBX), -12);
|
||||
|
@ -1072,6 +1072,7 @@ static void ems_usb_disconnect(struct usb_interface *intf)
|
||||
usb_free_urb(dev->intr_urb);
|
||||
|
||||
kfree(dev->intr_in_buffer);
|
||||
kfree(dev->tx_msg_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,6 +333,7 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev,
|
||||
|
||||
memset(&io_sq->desc_addr, 0x0, sizeof(io_sq->desc_addr));
|
||||
|
||||
io_sq->dma_addr_bits = ena_dev->dma_addr_bits;
|
||||
io_sq->desc_entry_size =
|
||||
(io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX) ?
|
||||
sizeof(struct ena_eth_io_tx_desc) :
|
||||
|
@ -1111,14 +1111,14 @@ static void xgbe_phy_adjust_link(struct xgbe_prv_data *pdata)
|
||||
|
||||
if (pdata->tx_pause != pdata->phy.tx_pause) {
|
||||
new_state = 1;
|
||||
pdata->hw_if.config_tx_flow_control(pdata);
|
||||
pdata->tx_pause = pdata->phy.tx_pause;
|
||||
pdata->hw_if.config_tx_flow_control(pdata);
|
||||
}
|
||||
|
||||
if (pdata->rx_pause != pdata->phy.rx_pause) {
|
||||
new_state = 1;
|
||||
pdata->hw_if.config_rx_flow_control(pdata);
|
||||
pdata->rx_pause = pdata->phy.rx_pause;
|
||||
pdata->hw_if.config_rx_flow_control(pdata);
|
||||
}
|
||||
|
||||
/* Speed support */
|
||||
|
@ -3072,6 +3072,7 @@ static void cxgb_del_udp_tunnel(struct net_device *netdev,
|
||||
|
||||
adapter->geneve_port = 0;
|
||||
t4_write_reg(adapter, MPS_RX_GENEVE_TYPE_A, 0);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@ -3157,6 +3158,7 @@ static void cxgb_add_udp_tunnel(struct net_device *netdev,
|
||||
|
||||
t4_write_reg(adapter, MPS_RX_GENEVE_TYPE_A,
|
||||
GENEVE_V(be16_to_cpu(ti->port)) | GENEVE_EN_F);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -2047,28 +2047,42 @@ static int enic_stop(struct net_device *netdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _enic_change_mtu(struct net_device *netdev, int new_mtu)
|
||||
{
|
||||
bool running = netif_running(netdev);
|
||||
int err = 0;
|
||||
|
||||
ASSERT_RTNL();
|
||||
if (running) {
|
||||
err = enic_stop(netdev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
netdev->mtu = new_mtu;
|
||||
|
||||
if (running) {
|
||||
err = enic_open(netdev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int enic_change_mtu(struct net_device *netdev, int new_mtu)
|
||||
{
|
||||
struct enic *enic = netdev_priv(netdev);
|
||||
int running = netif_running(netdev);
|
||||
|
||||
if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (running)
|
||||
enic_stop(netdev);
|
||||
|
||||
netdev->mtu = new_mtu;
|
||||
|
||||
if (netdev->mtu > enic->port_mtu)
|
||||
netdev_warn(netdev,
|
||||
"interface MTU (%d) set higher than port MTU (%d)\n",
|
||||
netdev->mtu, enic->port_mtu);
|
||||
"interface MTU (%d) set higher than port MTU (%d)\n",
|
||||
netdev->mtu, enic->port_mtu);
|
||||
|
||||
if (running)
|
||||
enic_open(netdev);
|
||||
|
||||
return 0;
|
||||
return _enic_change_mtu(netdev, new_mtu);
|
||||
}
|
||||
|
||||
static void enic_change_mtu_work(struct work_struct *work)
|
||||
@ -2076,47 +2090,9 @@ static void enic_change_mtu_work(struct work_struct *work)
|
||||
struct enic *enic = container_of(work, struct enic, change_mtu_work);
|
||||
struct net_device *netdev = enic->netdev;
|
||||
int new_mtu = vnic_dev_mtu(enic->vdev);
|
||||
int err;
|
||||
unsigned int i;
|
||||
|
||||
new_mtu = max_t(int, ENIC_MIN_MTU, min_t(int, ENIC_MAX_MTU, new_mtu));
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
/* Stop RQ */
|
||||
del_timer_sync(&enic->notify_timer);
|
||||
|
||||
for (i = 0; i < enic->rq_count; i++)
|
||||
napi_disable(&enic->napi[i]);
|
||||
|
||||
vnic_intr_mask(&enic->intr[0]);
|
||||
enic_synchronize_irqs(enic);
|
||||
err = vnic_rq_disable(&enic->rq[0]);
|
||||
if (err) {
|
||||
rtnl_unlock();
|
||||
netdev_err(netdev, "Unable to disable RQ.\n");
|
||||
return;
|
||||
}
|
||||
vnic_rq_clean(&enic->rq[0], enic_free_rq_buf);
|
||||
vnic_cq_clean(&enic->cq[0]);
|
||||
vnic_intr_clean(&enic->intr[0]);
|
||||
|
||||
/* Fill RQ with new_mtu-sized buffers */
|
||||
netdev->mtu = new_mtu;
|
||||
vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
|
||||
/* Need at least one buffer on ring to get going */
|
||||
if (vnic_rq_desc_used(&enic->rq[0]) == 0) {
|
||||
rtnl_unlock();
|
||||
netdev_err(netdev, "Unable to alloc receive buffers.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start RQ */
|
||||
vnic_rq_enable(&enic->rq[0]);
|
||||
napi_enable(&enic->napi[0]);
|
||||
vnic_intr_unmask(&enic->intr[0]);
|
||||
enic_notify_timer_start(enic);
|
||||
|
||||
(void)_enic_change_mtu(netdev, new_mtu);
|
||||
rtnl_unlock();
|
||||
|
||||
netdev_info(netdev, "interface MTU set as %d\n", netdev->mtu);
|
||||
|
@ -983,6 +983,7 @@ static int nic_dev_init(struct pci_dev *pdev)
|
||||
hinic_hwdev_cb_register(nic_dev->hwdev, HINIC_MGMT_MSG_CMD_LINK_STATUS,
|
||||
nic_dev, link_status_event_handler);
|
||||
|
||||
SET_NETDEV_DEV(netdev, &pdev->dev);
|
||||
err = register_netdev(netdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to register netdev\n");
|
||||
|
@ -80,7 +80,7 @@ nfp_flower_repr_get_type_and_port(struct nfp_app *app, u32 port_id, u8 *port)
|
||||
return NFP_REPR_TYPE_VF;
|
||||
}
|
||||
|
||||
return NFP_FLOWER_CMSG_PORT_TYPE_UNSPEC;
|
||||
return __NFP_REPR_TYPE_MAX;
|
||||
}
|
||||
|
||||
static struct net_device *
|
||||
@ -91,6 +91,8 @@ nfp_flower_repr_get(struct nfp_app *app, u32 port_id)
|
||||
u8 port = 0;
|
||||
|
||||
repr_type = nfp_flower_repr_get_type_and_port(app, port_id, &port);
|
||||
if (repr_type > NFP_REPR_TYPE_MAX)
|
||||
return NULL;
|
||||
|
||||
reprs = rcu_dereference(app->reprs[repr_type]);
|
||||
if (!reprs)
|
||||
|
@ -53,7 +53,7 @@
|
||||
#include "dwmac1000.h"
|
||||
#include "hwif.h"
|
||||
|
||||
#define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
|
||||
#define STMMAC_ALIGN(x) __ALIGN_KERNEL(x, SMP_CACHE_BYTES)
|
||||
#define TSO_MAX_BUFF_SIZE (SZ_16K - 1)
|
||||
|
||||
/* Module parameters */
|
||||
|
@ -207,6 +207,7 @@ void nsim_devlink_teardown(struct netdevsim *ns)
|
||||
struct net *net = nsim_to_net(ns);
|
||||
bool *reg_devlink = net_generic(net, nsim_devlink_id);
|
||||
|
||||
devlink_resources_unregister(ns->devlink, NULL);
|
||||
devlink_unregister(ns->devlink);
|
||||
devlink_free(ns->devlink);
|
||||
ns->devlink = NULL;
|
||||
|
@ -218,7 +218,7 @@ out:
|
||||
|
||||
static int mdio_mux_iproc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct iproc_mdiomux_desc *md = dev_get_platdata(&pdev->dev);
|
||||
struct iproc_mdiomux_desc *md = platform_get_drvdata(pdev);
|
||||
|
||||
mdio_mux_uninit(md->mux_handle);
|
||||
mdiobus_unregister(md->mii_bus);
|
||||
|
@ -1242,6 +1242,8 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
|
||||
mod_timer(&dev->stat_monitor,
|
||||
jiffies + STAT_UPDATE_TIMER);
|
||||
}
|
||||
|
||||
tasklet_schedule(&dev->bh);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -586,7 +586,8 @@ static struct sk_buff *receive_small(struct net_device *dev,
|
||||
struct receive_queue *rq,
|
||||
void *buf, void *ctx,
|
||||
unsigned int len,
|
||||
unsigned int *xdp_xmit)
|
||||
unsigned int *xdp_xmit,
|
||||
unsigned int *rbytes)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct bpf_prog *xdp_prog;
|
||||
@ -601,6 +602,7 @@ static struct sk_buff *receive_small(struct net_device *dev,
|
||||
int err;
|
||||
|
||||
len -= vi->hdr_len;
|
||||
*rbytes += len;
|
||||
|
||||
rcu_read_lock();
|
||||
xdp_prog = rcu_dereference(rq->xdp_prog);
|
||||
@ -705,11 +707,13 @@ static struct sk_buff *receive_big(struct net_device *dev,
|
||||
struct virtnet_info *vi,
|
||||
struct receive_queue *rq,
|
||||
void *buf,
|
||||
unsigned int len)
|
||||
unsigned int len,
|
||||
unsigned int *rbytes)
|
||||
{
|
||||
struct page *page = buf;
|
||||
struct sk_buff *skb = page_to_skb(vi, rq, page, 0, len, PAGE_SIZE);
|
||||
|
||||
*rbytes += len - vi->hdr_len;
|
||||
if (unlikely(!skb))
|
||||
goto err;
|
||||
|
||||
@ -727,7 +731,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
|
||||
void *buf,
|
||||
void *ctx,
|
||||
unsigned int len,
|
||||
unsigned int *xdp_xmit)
|
||||
unsigned int *xdp_xmit,
|
||||
unsigned int *rbytes)
|
||||
{
|
||||
struct virtio_net_hdr_mrg_rxbuf *hdr = buf;
|
||||
u16 num_buf = virtio16_to_cpu(vi->vdev, hdr->num_buffers);
|
||||
@ -740,6 +745,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
|
||||
int err;
|
||||
|
||||
head_skb = NULL;
|
||||
*rbytes += len - vi->hdr_len;
|
||||
|
||||
rcu_read_lock();
|
||||
xdp_prog = rcu_dereference(rq->xdp_prog);
|
||||
@ -877,6 +883,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
|
||||
goto err_buf;
|
||||
}
|
||||
|
||||
*rbytes += len;
|
||||
page = virt_to_head_page(buf);
|
||||
|
||||
truesize = mergeable_ctx_to_truesize(ctx);
|
||||
@ -932,6 +939,7 @@ err_skb:
|
||||
dev->stats.rx_length_errors++;
|
||||
break;
|
||||
}
|
||||
*rbytes += len;
|
||||
page = virt_to_head_page(buf);
|
||||
put_page(page);
|
||||
}
|
||||
@ -942,14 +950,13 @@ xdp_xmit:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
|
||||
void *buf, unsigned int len, void **ctx,
|
||||
unsigned int *xdp_xmit)
|
||||
static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
|
||||
void *buf, unsigned int len, void **ctx,
|
||||
unsigned int *xdp_xmit, unsigned int *rbytes)
|
||||
{
|
||||
struct net_device *dev = vi->dev;
|
||||
struct sk_buff *skb;
|
||||
struct virtio_net_hdr_mrg_rxbuf *hdr;
|
||||
int ret;
|
||||
|
||||
if (unlikely(len < vi->hdr_len + ETH_HLEN)) {
|
||||
pr_debug("%s: short packet %i\n", dev->name, len);
|
||||
@ -961,23 +968,22 @@ static int receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
|
||||
} else {
|
||||
put_page(virt_to_head_page(buf));
|
||||
}
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vi->mergeable_rx_bufs)
|
||||
skb = receive_mergeable(dev, vi, rq, buf, ctx, len, xdp_xmit);
|
||||
skb = receive_mergeable(dev, vi, rq, buf, ctx, len, xdp_xmit,
|
||||
rbytes);
|
||||
else if (vi->big_packets)
|
||||
skb = receive_big(dev, vi, rq, buf, len);
|
||||
skb = receive_big(dev, vi, rq, buf, len, rbytes);
|
||||
else
|
||||
skb = receive_small(dev, vi, rq, buf, ctx, len, xdp_xmit);
|
||||
skb = receive_small(dev, vi, rq, buf, ctx, len, xdp_xmit, rbytes);
|
||||
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
hdr = skb_vnet_hdr(skb);
|
||||
|
||||
ret = skb->len;
|
||||
|
||||
if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID)
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
@ -994,12 +1000,11 @@ static int receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
|
||||
ntohs(skb->protocol), skb->len, skb->pkt_type);
|
||||
|
||||
napi_gro_receive(&rq->napi, skb);
|
||||
return ret;
|
||||
return;
|
||||
|
||||
frame_err:
|
||||
dev->stats.rx_frame_errors++;
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unlike mergeable buffers, all buffers are allocated to the
|
||||
@ -1249,13 +1254,13 @@ static int virtnet_receive(struct receive_queue *rq, int budget,
|
||||
|
||||
while (received < budget &&
|
||||
(buf = virtqueue_get_buf_ctx(rq->vq, &len, &ctx))) {
|
||||
bytes += receive_buf(vi, rq, buf, len, ctx, xdp_xmit);
|
||||
receive_buf(vi, rq, buf, len, ctx, xdp_xmit, &bytes);
|
||||
received++;
|
||||
}
|
||||
} else {
|
||||
while (received < budget &&
|
||||
(buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
|
||||
bytes += receive_buf(vi, rq, buf, len, NULL, xdp_xmit);
|
||||
receive_buf(vi, rq, buf, len, NULL, xdp_xmit, &bytes);
|
||||
received++;
|
||||
}
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ struct netfront_cb {
|
||||
/* IRQ name is queue name with "-tx" or "-rx" appended */
|
||||
#define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3)
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(module_load_q);
|
||||
static DECLARE_WAIT_QUEUE_HEAD(module_unload_q);
|
||||
|
||||
struct netfront_stats {
|
||||
@ -1330,6 +1331,11 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
xenbus_switch_state(dev, XenbusStateInitialising);
|
||||
wait_event(module_load_q,
|
||||
xenbus_read_driver_state(dev->otherend) !=
|
||||
XenbusStateClosed &&
|
||||
xenbus_read_driver_state(dev->otherend) !=
|
||||
XenbusStateUnknown);
|
||||
return netdev;
|
||||
|
||||
exit:
|
||||
|
@ -378,7 +378,7 @@ static int array_map_check_btf(const struct bpf_map *map, const struct btf *btf,
|
||||
return -EINVAL;
|
||||
|
||||
value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
|
||||
if (!value_type || value_size > map->value_size)
|
||||
if (!value_type || value_size != map->value_size)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
|
@ -1519,9 +1519,9 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
||||
{
|
||||
bool is_union = BTF_INFO_KIND(t->info) == BTF_KIND_UNION;
|
||||
const struct btf_member *member;
|
||||
u32 meta_needed, last_offset;
|
||||
struct btf *btf = env->btf;
|
||||
u32 struct_size = t->size;
|
||||
u32 meta_needed;
|
||||
u16 i;
|
||||
|
||||
meta_needed = btf_type_vlen(t) * sizeof(*member);
|
||||
@ -1534,6 +1534,7 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
||||
|
||||
btf_verifier_log_type(env, t, NULL);
|
||||
|
||||
last_offset = 0;
|
||||
for_each_member(i, t, member) {
|
||||
if (!btf_name_offset_valid(btf, member->name_off)) {
|
||||
btf_verifier_log_member(env, t, member,
|
||||
@ -1555,6 +1556,16 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ">" instead of ">=" because the last member could be
|
||||
* "char a[0];"
|
||||
*/
|
||||
if (last_offset > member->offset) {
|
||||
btf_verifier_log_member(env, t, member,
|
||||
"Invalid member bits_offset");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (BITS_ROUNDUP_BYTES(member->offset) > struct_size) {
|
||||
btf_verifier_log_member(env, t, member,
|
||||
"Memmber bits_offset exceeds its struct size");
|
||||
@ -1562,6 +1573,7 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
|
||||
}
|
||||
|
||||
btf_verifier_log_member(env, t, member, NULL);
|
||||
last_offset = member->offset;
|
||||
}
|
||||
|
||||
return meta_needed;
|
||||
|
@ -7149,16 +7149,19 @@ int dev_change_tx_queue_len(struct net_device *dev, unsigned long new_len)
|
||||
dev->tx_queue_len = new_len;
|
||||
res = call_netdevice_notifiers(NETDEV_CHANGE_TX_QUEUE_LEN, dev);
|
||||
res = notifier_to_errno(res);
|
||||
if (res) {
|
||||
netdev_err(dev,
|
||||
"refused to change device tx_queue_len\n");
|
||||
dev->tx_queue_len = orig_len;
|
||||
return res;
|
||||
}
|
||||
return dev_qdisc_change_tx_queue_len(dev);
|
||||
if (res)
|
||||
goto err_rollback;
|
||||
res = dev_qdisc_change_tx_queue_len(dev);
|
||||
if (res)
|
||||
goto err_rollback;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_rollback:
|
||||
netdev_err(dev, "refused to change device tx_queue_len\n");
|
||||
dev->tx_queue_len = orig_len;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1712,24 +1712,26 @@ static const struct bpf_func_proto bpf_skb_load_bytes_proto = {
|
||||
BPF_CALL_5(bpf_skb_load_bytes_relative, const struct sk_buff *, skb,
|
||||
u32, offset, void *, to, u32, len, u32, start_header)
|
||||
{
|
||||
u8 *end = skb_tail_pointer(skb);
|
||||
u8 *net = skb_network_header(skb);
|
||||
u8 *mac = skb_mac_header(skb);
|
||||
u8 *ptr;
|
||||
|
||||
if (unlikely(offset > 0xffff || len > skb_headlen(skb)))
|
||||
if (unlikely(offset > 0xffff || len > (end - mac)))
|
||||
goto err_clear;
|
||||
|
||||
switch (start_header) {
|
||||
case BPF_HDR_START_MAC:
|
||||
ptr = skb_mac_header(skb) + offset;
|
||||
ptr = mac + offset;
|
||||
break;
|
||||
case BPF_HDR_START_NET:
|
||||
ptr = skb_network_header(skb) + offset;
|
||||
ptr = net + offset;
|
||||
break;
|
||||
default:
|
||||
goto err_clear;
|
||||
}
|
||||
|
||||
if (likely(ptr >= skb_mac_header(skb) &&
|
||||
ptr + len <= skb_tail_pointer(skb))) {
|
||||
if (likely(ptr >= mac && ptr + len <= end)) {
|
||||
memcpy(to, ptr, len);
|
||||
return 0;
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ static int bpf_parse_prog(struct nlattr *attr, struct bpf_lwt_prog *prog,
|
||||
if (!tb[LWT_BPF_PROG_FD] || !tb[LWT_BPF_PROG_NAME])
|
||||
return -EINVAL;
|
||||
|
||||
prog->name = nla_memdup(tb[LWT_BPF_PROG_NAME], GFP_KERNEL);
|
||||
prog->name = nla_memdup(tb[LWT_BPF_PROG_NAME], GFP_ATOMIC);
|
||||
if (!prog->name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -345,7 +345,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
|
||||
rcu_read_lock();
|
||||
/* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */
|
||||
xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
|
||||
xa->zc_alloc->free(xa->zc_alloc, handle);
|
||||
if (!WARN_ON_ONCE(!xa))
|
||||
xa->zc_alloc->free(xa->zc_alloc, handle);
|
||||
rcu_read_unlock();
|
||||
default:
|
||||
/* Not possible, checked in xdp_rxq_info_reg_mem_model() */
|
||||
|
@ -292,19 +292,19 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
|
||||
return ip_hdr(skb)->daddr;
|
||||
|
||||
in_dev = __in_dev_get_rcu(dev);
|
||||
BUG_ON(!in_dev);
|
||||
|
||||
net = dev_net(dev);
|
||||
|
||||
scope = RT_SCOPE_UNIVERSE;
|
||||
if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) {
|
||||
bool vmark = in_dev && IN_DEV_SRC_VMARK(in_dev);
|
||||
struct flowi4 fl4 = {
|
||||
.flowi4_iif = LOOPBACK_IFINDEX,
|
||||
.flowi4_oif = l3mdev_master_ifindex_rcu(dev),
|
||||
.daddr = ip_hdr(skb)->saddr,
|
||||
.flowi4_tos = RT_TOS(ip_hdr(skb)->tos),
|
||||
.flowi4_scope = scope,
|
||||
.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0,
|
||||
.flowi4_mark = vmark ? skb->mark : 0,
|
||||
};
|
||||
if (!fib_lookup(net, &fl4, &res, 0))
|
||||
return FIB_RES_PREFSRC(net, res);
|
||||
|
@ -1387,7 +1387,8 @@ static void ip_mc_hash_remove(struct in_device *in_dev,
|
||||
/*
|
||||
* A socket has joined a multicast group on device dev.
|
||||
*/
|
||||
void __ip_mc_inc_group(struct in_device *in_dev, __be32 addr, unsigned int mode)
|
||||
static void __ip_mc_inc_group(struct in_device *in_dev, __be32 addr,
|
||||
unsigned int mode)
|
||||
{
|
||||
struct ip_mc_list *im;
|
||||
#ifdef CONFIG_IP_MULTICAST
|
||||
|
@ -354,6 +354,10 @@ static u32 bbr_target_cwnd(struct sock *sk, u32 bw, int gain)
|
||||
/* Reduce delayed ACKs by rounding up cwnd to the next even number. */
|
||||
cwnd = (cwnd + 1) & ~1U;
|
||||
|
||||
/* Ensure gain cycling gets inflight above BDP even for small BDPs. */
|
||||
if (bbr->mode == BBR_PROBE_BW && gain > BBR_UNIT)
|
||||
cwnd += 2;
|
||||
|
||||
return cwnd;
|
||||
}
|
||||
|
||||
|
@ -246,8 +246,15 @@ static void tcp_ecn_queue_cwr(struct tcp_sock *tp)
|
||||
|
||||
static void tcp_ecn_accept_cwr(struct tcp_sock *tp, const struct sk_buff *skb)
|
||||
{
|
||||
if (tcp_hdr(skb)->cwr)
|
||||
if (tcp_hdr(skb)->cwr) {
|
||||
tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR;
|
||||
|
||||
/* If the sender is telling us it has entered CWR, then its
|
||||
* cwnd may be very low (even just 1 packet), so we should ACK
|
||||
* immediately.
|
||||
*/
|
||||
tcp_enter_quickack_mode((struct sock *)tp, 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void tcp_ecn_withdraw_cwr(struct tcp_sock *tp)
|
||||
|
@ -669,8 +669,10 @@ skip_cow:
|
||||
|
||||
sg_init_table(sg, nfrags);
|
||||
ret = skb_to_sgvec(skb, sg, 0, skb->len);
|
||||
if (unlikely(ret < 0))
|
||||
if (unlikely(ret < 0)) {
|
||||
kfree(tmp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
|
@ -167,11 +167,22 @@ struct fib6_info *fib6_info_alloc(gfp_t gfp_flags)
|
||||
return f6i;
|
||||
}
|
||||
|
||||
static void fib6_metrics_release(struct fib6_info *f6i)
|
||||
{
|
||||
struct dst_metrics *m;
|
||||
|
||||
if (!f6i)
|
||||
return;
|
||||
|
||||
m = f6i->fib6_metrics;
|
||||
if (m != &dst_default_metrics && refcount_dec_and_test(&m->refcnt))
|
||||
kfree(m);
|
||||
}
|
||||
|
||||
void fib6_info_destroy_rcu(struct rcu_head *head)
|
||||
{
|
||||
struct fib6_info *f6i = container_of(head, struct fib6_info, rcu);
|
||||
struct rt6_exception_bucket *bucket;
|
||||
struct dst_metrics *m;
|
||||
|
||||
WARN_ON(f6i->fib6_node);
|
||||
|
||||
@ -201,9 +212,7 @@ void fib6_info_destroy_rcu(struct rcu_head *head)
|
||||
if (f6i->fib6_nh.nh_dev)
|
||||
dev_put(f6i->fib6_nh.nh_dev);
|
||||
|
||||
m = f6i->fib6_metrics;
|
||||
if (m != &dst_default_metrics && refcount_dec_and_test(&m->refcnt))
|
||||
kfree(m);
|
||||
fib6_metrics_release(f6i);
|
||||
|
||||
kfree(f6i);
|
||||
}
|
||||
@ -887,6 +896,7 @@ static void fib6_drop_pcpu_from(struct fib6_info *f6i,
|
||||
|
||||
from = rcu_dereference_protected(pcpu_rt->from,
|
||||
lockdep_is_held(&table->tb6_lock));
|
||||
fib6_metrics_release(from);
|
||||
rcu_assign_pointer(pcpu_rt->from, NULL);
|
||||
fib6_info_release(from);
|
||||
}
|
||||
|
@ -480,10 +480,6 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
|
||||
goto tx_err_dst_release;
|
||||
}
|
||||
|
||||
skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev)));
|
||||
skb_dst_set(skb, dst);
|
||||
skb->dev = skb_dst(skb)->dev;
|
||||
|
||||
mtu = dst_mtu(dst);
|
||||
if (!skb->ignore_df && skb->len > mtu) {
|
||||
skb_dst_update_pmtu(skb, mtu);
|
||||
@ -498,9 +494,14 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
|
||||
htonl(mtu));
|
||||
}
|
||||
|
||||
return -EMSGSIZE;
|
||||
err = -EMSGSIZE;
|
||||
goto tx_err_dst_release;
|
||||
}
|
||||
|
||||
skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev)));
|
||||
skb_dst_set(skb, dst);
|
||||
skb->dev = skb_dst(skb)->dev;
|
||||
|
||||
err = dst_output(t->net, skb->sk, skb);
|
||||
if (net_xmit_eval(err) == 0) {
|
||||
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
|
||||
|
@ -1009,6 +1009,11 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
|
||||
return err;
|
||||
}
|
||||
|
||||
if (nlk->ngroups == 0)
|
||||
groups = 0;
|
||||
else
|
||||
groups &= (1ULL << nlk->ngroups) - 1;
|
||||
|
||||
bound = nlk->bound;
|
||||
if (bound) {
|
||||
/* Ensure nlk->portid is up-to-date. */
|
||||
|
@ -211,6 +211,7 @@ static struct dp_meter *dp_meter_create(struct nlattr **a)
|
||||
if (!meter)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
meter->id = nla_get_u32(a[OVS_METER_ATTR_ID]);
|
||||
meter->used = div_u64(ktime_get_ns(), 1000 * 1000);
|
||||
meter->kbps = a[OVS_METER_ATTR_KBPS] ? 1 : 0;
|
||||
meter->keep_stats = !a[OVS_METER_ATTR_CLEAR];
|
||||
@ -280,6 +281,10 @@ static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
||||
u32 meter_id;
|
||||
bool failed;
|
||||
|
||||
if (!a[OVS_METER_ATTR_ID]) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
meter = dp_meter_create(a);
|
||||
if (IS_ERR_OR_NULL(meter))
|
||||
return PTR_ERR(meter);
|
||||
@ -298,11 +303,6 @@ static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
if (!a[OVS_METER_ATTR_ID]) {
|
||||
err = -ENODEV;
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
|
||||
|
||||
/* Cannot fail after this. */
|
||||
|
@ -344,6 +344,11 @@ struct rds_ib_mr *rds_ib_reg_frmr(struct rds_ib_device *rds_ibdev,
|
||||
struct rds_ib_frmr *frmr;
|
||||
int ret;
|
||||
|
||||
if (!ic) {
|
||||
/* TODO: Add FRWR support for RDS_GET_MR using proxy qp*/
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
do {
|
||||
if (ibmr)
|
||||
rds_ib_free_frmr(ibmr, true);
|
||||
|
@ -115,7 +115,8 @@ void rds_ib_get_mr_info(struct rds_ib_device *rds_ibdev,
|
||||
struct rds_info_rdma_connection *iinfo);
|
||||
void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *);
|
||||
void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
|
||||
struct rds_sock *rs, u32 *key_ret);
|
||||
struct rds_sock *rs, u32 *key_ret,
|
||||
struct rds_connection *conn);
|
||||
void rds_ib_sync_mr(void *trans_private, int dir);
|
||||
void rds_ib_free_mr(void *trans_private, int invalidate);
|
||||
void rds_ib_flush_mrs(void);
|
||||
|
@ -537,11 +537,12 @@ void rds_ib_flush_mrs(void)
|
||||
}
|
||||
|
||||
void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
|
||||
struct rds_sock *rs, u32 *key_ret)
|
||||
struct rds_sock *rs, u32 *key_ret,
|
||||
struct rds_connection *conn)
|
||||
{
|
||||
struct rds_ib_device *rds_ibdev;
|
||||
struct rds_ib_mr *ibmr = NULL;
|
||||
struct rds_ib_connection *ic = rs->rs_conn->c_transport_data;
|
||||
struct rds_ib_connection *ic = NULL;
|
||||
int ret;
|
||||
|
||||
rds_ibdev = rds_ib_get_device(rs->rs_bound_addr);
|
||||
@ -550,6 +551,9 @@ void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (conn)
|
||||
ic = conn->c_transport_data;
|
||||
|
||||
if (!rds_ibdev->mr_8k_pool || !rds_ibdev->mr_1m_pool) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
@ -559,17 +563,18 @@ void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
|
||||
ibmr = rds_ib_reg_frmr(rds_ibdev, ic, sg, nents, key_ret);
|
||||
else
|
||||
ibmr = rds_ib_reg_fmr(rds_ibdev, sg, nents, key_ret);
|
||||
if (ibmr)
|
||||
rds_ibdev = NULL;
|
||||
if (IS_ERR(ibmr)) {
|
||||
ret = PTR_ERR(ibmr);
|
||||
pr_warn("RDS/IB: rds_ib_get_mr failed (errno=%d)\n", ret);
|
||||
} else {
|
||||
return ibmr;
|
||||
}
|
||||
|
||||
out:
|
||||
if (!ibmr)
|
||||
pr_warn("RDS/IB: rds_ib_get_mr failed (errno=%d)\n", ret);
|
||||
|
||||
if (rds_ibdev)
|
||||
rds_ib_dev_put(rds_ibdev);
|
||||
|
||||
return ibmr;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *pool)
|
||||
|
@ -170,7 +170,8 @@ static int rds_pin_pages(unsigned long user_addr, unsigned int nr_pages,
|
||||
}
|
||||
|
||||
static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
|
||||
u64 *cookie_ret, struct rds_mr **mr_ret)
|
||||
u64 *cookie_ret, struct rds_mr **mr_ret,
|
||||
struct rds_conn_path *cp)
|
||||
{
|
||||
struct rds_mr *mr = NULL, *found;
|
||||
unsigned int nr_pages;
|
||||
@ -269,7 +270,8 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
|
||||
* Note that dma_map() implies that pending writes are
|
||||
* flushed to RAM, so no dma_sync is needed here. */
|
||||
trans_private = rs->rs_transport->get_mr(sg, nents, rs,
|
||||
&mr->r_key);
|
||||
&mr->r_key,
|
||||
cp ? cp->cp_conn : NULL);
|
||||
|
||||
if (IS_ERR(trans_private)) {
|
||||
for (i = 0 ; i < nents; i++)
|
||||
@ -330,7 +332,7 @@ int rds_get_mr(struct rds_sock *rs, char __user *optval, int optlen)
|
||||
sizeof(struct rds_get_mr_args)))
|
||||
return -EFAULT;
|
||||
|
||||
return __rds_rdma_map(rs, &args, NULL, NULL);
|
||||
return __rds_rdma_map(rs, &args, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen)
|
||||
@ -354,7 +356,7 @@ int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen)
|
||||
new_args.cookie_addr = args.cookie_addr;
|
||||
new_args.flags = args.flags;
|
||||
|
||||
return __rds_rdma_map(rs, &new_args, NULL, NULL);
|
||||
return __rds_rdma_map(rs, &new_args, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -782,7 +784,8 @@ int rds_cmsg_rdma_map(struct rds_sock *rs, struct rds_message *rm,
|
||||
rm->m_rdma_cookie != 0)
|
||||
return -EINVAL;
|
||||
|
||||
return __rds_rdma_map(rs, CMSG_DATA(cmsg), &rm->m_rdma_cookie, &rm->rdma.op_rdma_mr);
|
||||
return __rds_rdma_map(rs, CMSG_DATA(cmsg), &rm->m_rdma_cookie,
|
||||
&rm->rdma.op_rdma_mr, rm->m_conn_path);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -464,6 +464,8 @@ struct rds_message {
|
||||
struct scatterlist *op_sg;
|
||||
} data;
|
||||
};
|
||||
|
||||
struct rds_conn_path *m_conn_path;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -544,7 +546,8 @@ struct rds_transport {
|
||||
unsigned int avail);
|
||||
void (*exit)(void);
|
||||
void *(*get_mr)(struct scatterlist *sg, unsigned long nr_sg,
|
||||
struct rds_sock *rs, u32 *key_ret);
|
||||
struct rds_sock *rs, u32 *key_ret,
|
||||
struct rds_connection *conn);
|
||||
void (*sync_mr)(void *trans_private, int direction);
|
||||
void (*free_mr)(void *trans_private, int invalidate);
|
||||
void (*flush_mrs)(void);
|
||||
|
@ -1169,6 +1169,13 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
|
||||
rs->rs_conn = conn;
|
||||
}
|
||||
|
||||
if (conn->c_trans->t_mp_capable)
|
||||
cpath = &conn->c_path[rds_send_mprds_hash(rs, conn)];
|
||||
else
|
||||
cpath = &conn->c_path[0];
|
||||
|
||||
rm->m_conn_path = cpath;
|
||||
|
||||
/* Parse any control messages the user may have included. */
|
||||
ret = rds_cmsg_send(rs, rm, msg, &allocated_mr);
|
||||
if (ret) {
|
||||
@ -1192,11 +1199,6 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (conn->c_trans->t_mp_capable)
|
||||
cpath = &conn->c_path[rds_send_mprds_hash(rs, conn)];
|
||||
else
|
||||
cpath = &conn->c_path[0];
|
||||
|
||||
if (rds_destroy_pending(conn)) {
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
|
@ -89,6 +89,7 @@
|
||||
#include <linux/magic.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <linux/nospec.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/unistd.h>
|
||||
@ -2522,6 +2523,7 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
|
||||
|
||||
if (call < 1 || call > SYS_SENDMMSG)
|
||||
return -EINVAL;
|
||||
call = array_index_nospec(call, SYS_SENDMMSG + 1);
|
||||
|
||||
len = nargs[call];
|
||||
if (len > sizeof(a))
|
||||
@ -2688,7 +2690,8 @@ EXPORT_SYMBOL(sock_unregister);
|
||||
|
||||
bool sock_is_registered(int family)
|
||||
{
|
||||
return family < NPROTO && rcu_access_pointer(net_families[family]);
|
||||
return family < NPROTO &&
|
||||
rcu_access_pointer(net_families[array_index_nospec(family, NPROTO)]);
|
||||
}
|
||||
|
||||
static int __init sock_init(void)
|
||||
|
@ -250,7 +250,7 @@ static inline bool xskq_full_desc(struct xsk_queue *q)
|
||||
|
||||
static inline bool xskq_empty_desc(struct xsk_queue *q)
|
||||
{
|
||||
return xskq_nb_free(q, q->prod_tail, 1) == q->nentries;
|
||||
return xskq_nb_free(q, q->prod_tail, q->nentries) == q->nentries;
|
||||
}
|
||||
|
||||
void xskq_set_umem(struct xsk_queue *q, struct xdp_umem_props *umem_props);
|
||||
|
@ -2286,6 +2286,9 @@ struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
|
||||
if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE)
|
||||
return make_blackhole(net, dst_orig->ops->family, dst_orig);
|
||||
|
||||
if (IS_ERR(dst))
|
||||
dst_release(dst_orig);
|
||||
|
||||
return dst;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_lookup_route);
|
||||
|
@ -1025,10 +1025,12 @@ static inline int xfrm_nlmsg_multicast(struct net *net, struct sk_buff *skb,
|
||||
{
|
||||
struct sock *nlsk = rcu_dereference(net->xfrm.nlsk);
|
||||
|
||||
if (nlsk)
|
||||
return nlmsg_multicast(nlsk, skb, pid, group, GFP_ATOMIC);
|
||||
else
|
||||
return -1;
|
||||
if (!nlsk) {
|
||||
kfree_skb(skb);
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
return nlmsg_multicast(nlsk, skb, pid, group, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static inline unsigned int xfrm_spdinfo_msgsize(void)
|
||||
@ -1671,9 +1673,11 @@ static inline unsigned int userpolicy_type_attrsize(void)
|
||||
#ifdef CONFIG_XFRM_SUB_POLICY
|
||||
static int copy_to_user_policy_type(u8 type, struct sk_buff *skb)
|
||||
{
|
||||
struct xfrm_userpolicy_type upt = {
|
||||
.type = type,
|
||||
};
|
||||
struct xfrm_userpolicy_type upt;
|
||||
|
||||
/* Sadly there are two holes in struct xfrm_userpolicy_type */
|
||||
memset(&upt, 0, sizeof(upt));
|
||||
upt.type = type;
|
||||
|
||||
return nla_put(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt);
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ struct btf_type {
|
||||
*/
|
||||
#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
|
||||
#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16)
|
||||
#define BTF_INT_BITS(VAL) ((VAL) & 0x0000ffff)
|
||||
#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
|
||||
|
||||
/* Attributes stored in the BTF_INT_ENCODING */
|
||||
#define BTF_INT_SIGNED (1 << 0)
|
||||
|
@ -2,7 +2,6 @@
|
||||
/* Copyright (c) 2018 Facebook */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
@ -27,13 +26,13 @@ struct btf {
|
||||
struct btf_type **types;
|
||||
const char *strings;
|
||||
void *nohdr_data;
|
||||
uint32_t nr_types;
|
||||
uint32_t types_size;
|
||||
uint32_t data_size;
|
||||
__u32 nr_types;
|
||||
__u32 types_size;
|
||||
__u32 data_size;
|
||||
int fd;
|
||||
};
|
||||
|
||||
static const char *btf_name_by_offset(const struct btf *btf, uint32_t offset)
|
||||
static const char *btf_name_by_offset(const struct btf *btf, __u32 offset)
|
||||
{
|
||||
if (offset < btf->hdr->str_len)
|
||||
return &btf->strings[offset];
|
||||
@ -45,7 +44,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)
|
||||
{
|
||||
if (btf->types_size - btf->nr_types < 2) {
|
||||
struct btf_type **new_types;
|
||||
u32 expand_by, new_size;
|
||||
__u32 expand_by, new_size;
|
||||
|
||||
if (btf->types_size == BTF_MAX_NR_TYPES)
|
||||
return -E2BIG;
|
||||
@ -72,7 +71,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)
|
||||
static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log)
|
||||
{
|
||||
const struct btf_header *hdr = btf->hdr;
|
||||
u32 meta_left;
|
||||
__u32 meta_left;
|
||||
|
||||
if (btf->data_size < sizeof(struct btf_header)) {
|
||||
elog("BTF header not found\n");
|
||||
@ -151,7 +150,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
|
||||
|
||||
while (next_type < end_type) {
|
||||
struct btf_type *t = next_type;
|
||||
uint16_t vlen = BTF_INFO_VLEN(t->info);
|
||||
__u16 vlen = BTF_INFO_VLEN(t->info);
|
||||
int err;
|
||||
|
||||
next_type += sizeof(*t);
|
||||
@ -190,8 +189,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct btf_type *btf_type_by_id(const struct btf *btf,
|
||||
uint32_t type_id)
|
||||
const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 type_id)
|
||||
{
|
||||
if (type_id > btf->nr_types)
|
||||
return NULL;
|
||||
@ -209,7 +207,7 @@ static bool btf_type_is_void_or_null(const struct btf_type *t)
|
||||
return !t || btf_type_is_void(t);
|
||||
}
|
||||
|
||||
static int64_t btf_type_size(const struct btf_type *t)
|
||||
static __s64 btf_type_size(const struct btf_type *t)
|
||||
{
|
||||
switch (BTF_INFO_KIND(t->info)) {
|
||||
case BTF_KIND_INT:
|
||||
@ -226,15 +224,15 @@ static int64_t btf_type_size(const struct btf_type *t)
|
||||
|
||||
#define MAX_RESOLVE_DEPTH 32
|
||||
|
||||
int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)
|
||||
__s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
|
||||
{
|
||||
const struct btf_array *array;
|
||||
const struct btf_type *t;
|
||||
uint32_t nelems = 1;
|
||||
int64_t size = -1;
|
||||
__u32 nelems = 1;
|
||||
__s64 size = -1;
|
||||
int i;
|
||||
|
||||
t = btf_type_by_id(btf, type_id);
|
||||
t = btf__type_by_id(btf, type_id);
|
||||
for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t);
|
||||
i++) {
|
||||
size = btf_type_size(t);
|
||||
@ -259,7 +257,7 @@ int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
t = btf_type_by_id(btf, type_id);
|
||||
t = btf__type_by_id(btf, type_id);
|
||||
}
|
||||
|
||||
if (size < 0)
|
||||
@ -271,9 +269,9 @@ int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)
|
||||
return nelems * size;
|
||||
}
|
||||
|
||||
int32_t btf__find_by_name(const struct btf *btf, const char *type_name)
|
||||
__s32 btf__find_by_name(const struct btf *btf, const char *type_name)
|
||||
{
|
||||
uint32_t i;
|
||||
__u32 i;
|
||||
|
||||
if (!strcmp(type_name, "void"))
|
||||
return 0;
|
||||
@ -302,10 +300,9 @@ void btf__free(struct btf *btf)
|
||||
free(btf);
|
||||
}
|
||||
|
||||
struct btf *btf__new(uint8_t *data, uint32_t size,
|
||||
btf_print_fn_t err_log)
|
||||
struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
|
||||
{
|
||||
uint32_t log_buf_size = 0;
|
||||
__u32 log_buf_size = 0;
|
||||
char *log_buf = NULL;
|
||||
struct btf *btf;
|
||||
int err;
|
||||
|
@ -4,19 +4,21 @@
|
||||
#ifndef __BPF_BTF_H
|
||||
#define __BPF_BTF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define BTF_ELF_SEC ".BTF"
|
||||
|
||||
struct btf;
|
||||
struct btf_type;
|
||||
|
||||
typedef int (*btf_print_fn_t)(const char *, ...)
|
||||
__attribute__((format(printf, 1, 2)));
|
||||
|
||||
void btf__free(struct btf *btf);
|
||||
struct btf *btf__new(uint8_t *data, uint32_t size, btf_print_fn_t err_log);
|
||||
int32_t btf__find_by_name(const struct btf *btf, const char *type_name);
|
||||
int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id);
|
||||
struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
|
||||
__s32 btf__find_by_name(const struct btf *btf, const char *type_name);
|
||||
const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 id);
|
||||
__s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
|
||||
int btf__fd(const struct btf *btf);
|
||||
|
||||
#endif
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/btf.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/limits.h>
|
||||
#include <sys/stat.h>
|
||||
@ -216,8 +217,8 @@ struct bpf_map {
|
||||
size_t offset;
|
||||
int map_ifindex;
|
||||
struct bpf_map_def def;
|
||||
uint32_t btf_key_type_id;
|
||||
uint32_t btf_value_type_id;
|
||||
__u32 btf_key_type_id;
|
||||
__u32 btf_value_type_id;
|
||||
void *priv;
|
||||
bpf_map_clear_priv_t clear_priv;
|
||||
};
|
||||
@ -1014,68 +1015,72 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
|
||||
|
||||
static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
|
||||
{
|
||||
const struct btf_type *container_type;
|
||||
const struct btf_member *key, *value;
|
||||
struct bpf_map_def *def = &map->def;
|
||||
const size_t max_name = 256;
|
||||
int64_t key_size, value_size;
|
||||
int32_t key_id, value_id;
|
||||
char name[max_name];
|
||||
char container_name[max_name];
|
||||
__s64 key_size, value_size;
|
||||
__s32 container_id;
|
||||
|
||||
/* Find key type by name from BTF */
|
||||
if (snprintf(name, max_name, "%s_key", map->name) == max_name) {
|
||||
pr_warning("map:%s length of BTF key_type:%s_key is too long\n",
|
||||
if (snprintf(container_name, max_name, "____btf_map_%s", map->name) ==
|
||||
max_name) {
|
||||
pr_warning("map:%s length of '____btf_map_%s' is too long\n",
|
||||
map->name, map->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
key_id = btf__find_by_name(btf, name);
|
||||
if (key_id < 0) {
|
||||
pr_debug("map:%s key_type:%s cannot be found in BTF\n",
|
||||
map->name, name);
|
||||
return key_id;
|
||||
container_id = btf__find_by_name(btf, container_name);
|
||||
if (container_id < 0) {
|
||||
pr_debug("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n",
|
||||
map->name, container_name);
|
||||
return container_id;
|
||||
}
|
||||
|
||||
key_size = btf__resolve_size(btf, key_id);
|
||||
container_type = btf__type_by_id(btf, container_id);
|
||||
if (!container_type) {
|
||||
pr_warning("map:%s cannot find BTF type for container_id:%u\n",
|
||||
map->name, container_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT ||
|
||||
BTF_INFO_VLEN(container_type->info) < 2) {
|
||||
pr_warning("map:%s container_name:%s is an invalid container struct\n",
|
||||
map->name, container_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
key = (struct btf_member *)(container_type + 1);
|
||||
value = key + 1;
|
||||
|
||||
key_size = btf__resolve_size(btf, key->type);
|
||||
if (key_size < 0) {
|
||||
pr_warning("map:%s key_type:%s cannot get the BTF type_size\n",
|
||||
map->name, name);
|
||||
pr_warning("map:%s invalid BTF key_type_size\n",
|
||||
map->name);
|
||||
return key_size;
|
||||
}
|
||||
|
||||
if (def->key_size != key_size) {
|
||||
pr_warning("map:%s key_type:%s has BTF type_size:%u != key_size:%u\n",
|
||||
map->name, name, (unsigned int)key_size, def->key_size);
|
||||
pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n",
|
||||
map->name, (__u32)key_size, def->key_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Find value type from BTF */
|
||||
if (snprintf(name, max_name, "%s_value", map->name) == max_name) {
|
||||
pr_warning("map:%s length of BTF value_type:%s_value is too long\n",
|
||||
map->name, map->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
value_id = btf__find_by_name(btf, name);
|
||||
if (value_id < 0) {
|
||||
pr_debug("map:%s value_type:%s cannot be found in BTF\n",
|
||||
map->name, name);
|
||||
return value_id;
|
||||
}
|
||||
|
||||
value_size = btf__resolve_size(btf, value_id);
|
||||
value_size = btf__resolve_size(btf, value->type);
|
||||
if (value_size < 0) {
|
||||
pr_warning("map:%s value_type:%s cannot get the BTF type_size\n",
|
||||
map->name, name);
|
||||
pr_warning("map:%s invalid BTF value_type_size\n", map->name);
|
||||
return value_size;
|
||||
}
|
||||
|
||||
if (def->value_size != value_size) {
|
||||
pr_warning("map:%s value_type:%s has BTF type_size:%u != value_size:%u\n",
|
||||
map->name, name, (unsigned int)value_size, def->value_size);
|
||||
pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n",
|
||||
map->name, (__u32)value_size, def->value_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
map->btf_key_type_id = key_id;
|
||||
map->btf_value_type_id = value_id;
|
||||
map->btf_key_type_id = key->type;
|
||||
map->btf_value_type_id = value->type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2089,12 +2094,12 @@ const char *bpf_map__name(struct bpf_map *map)
|
||||
return map ? map->name : NULL;
|
||||
}
|
||||
|
||||
uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map)
|
||||
__u32 bpf_map__btf_key_type_id(const struct bpf_map *map)
|
||||
{
|
||||
return map ? map->btf_key_type_id : 0;
|
||||
}
|
||||
|
||||
uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map)
|
||||
__u32 bpf_map__btf_value_type_id(const struct bpf_map *map)
|
||||
{
|
||||
return map ? map->btf_value_type_id : 0;
|
||||
}
|
||||
@ -2268,8 +2273,8 @@ bpf_perf_event_read_simple(void *mem, unsigned long size,
|
||||
volatile struct perf_event_mmap_page *header = mem;
|
||||
__u64 data_tail = header->data_tail;
|
||||
__u64 data_head = header->data_head;
|
||||
int ret = LIBBPF_PERF_EVENT_ERROR;
|
||||
void *base, *begin, *end;
|
||||
int ret;
|
||||
|
||||
asm volatile("" ::: "memory"); /* in real code it should be smp_rmb() */
|
||||
if (data_head == data_tail)
|
||||
|
@ -244,8 +244,8 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
|
||||
int bpf_map__fd(struct bpf_map *map);
|
||||
const struct bpf_map_def *bpf_map__def(struct bpf_map *map);
|
||||
const char *bpf_map__name(struct bpf_map *map);
|
||||
uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map);
|
||||
uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map);
|
||||
__u32 bpf_map__btf_key_type_id(const struct bpf_map *map);
|
||||
__u32 bpf_map__btf_value_type_id(const struct bpf_map *map);
|
||||
|
||||
typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
|
||||
int bpf_map__set_priv(struct bpf_map *map, void *priv,
|
||||
|
@ -158,6 +158,15 @@ struct bpf_map_def {
|
||||
unsigned int numa_node;
|
||||
};
|
||||
|
||||
#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
|
||||
struct ____btf_map_##name { \
|
||||
type_key key; \
|
||||
type_val value; \
|
||||
}; \
|
||||
struct ____btf_map_##name \
|
||||
__attribute__ ((section(".maps." #name), used)) \
|
||||
____btf_map_##name = { }
|
||||
|
||||
static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
|
||||
(void *) BPF_FUNC_skb_load_bytes;
|
||||
static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) =
|
||||
|
@ -247,6 +247,34 @@ static struct btf_raw_test raw_tests[] = {
|
||||
.max_entries = 4,
|
||||
},
|
||||
|
||||
{
|
||||
.descr = "struct test #3 Invalid member offset",
|
||||
.raw_types = {
|
||||
/* int */ /* [1] */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
|
||||
/* int64 */ /* [2] */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 64, 8),
|
||||
|
||||
/* struct A { */ /* [3] */
|
||||
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 16),
|
||||
BTF_MEMBER_ENC(NAME_TBD, 1, 64), /* int m; */
|
||||
BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* int64 n; */
|
||||
/* } */
|
||||
BTF_END_RAW,
|
||||
},
|
||||
.str_sec = "\0A\0m\0n\0",
|
||||
.str_sec_size = sizeof("\0A\0m\0n\0"),
|
||||
.map_type = BPF_MAP_TYPE_ARRAY,
|
||||
.map_name = "struct_test3_map",
|
||||
.key_size = sizeof(int),
|
||||
.value_size = 16,
|
||||
.key_type_id = 1,
|
||||
.value_type_id = 3,
|
||||
.max_entries = 4,
|
||||
.btf_load_err = true,
|
||||
.err_str = "Invalid member bits_offset",
|
||||
},
|
||||
|
||||
/* Test member exceeds the size of struct.
|
||||
*
|
||||
* struct A {
|
||||
@ -479,7 +507,7 @@ static struct btf_raw_test raw_tests[] = {
|
||||
.key_size = sizeof(int),
|
||||
.value_size = sizeof(void *) * 4,
|
||||
.key_type_id = 1,
|
||||
.value_type_id = 4,
|
||||
.value_type_id = 5,
|
||||
.max_entries = 4,
|
||||
},
|
||||
|
||||
@ -1264,6 +1292,88 @@ static struct btf_raw_test raw_tests[] = {
|
||||
.err_str = "type != 0",
|
||||
},
|
||||
|
||||
{
|
||||
.descr = "arraymap invalid btf key (a bit field)",
|
||||
.raw_types = {
|
||||
/* int */ /* [1] */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
|
||||
/* 32 bit int with 32 bit offset */ /* [2] */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 32, 32, 8),
|
||||
BTF_END_RAW,
|
||||
},
|
||||
.str_sec = "",
|
||||
.str_sec_size = sizeof(""),
|
||||
.map_type = BPF_MAP_TYPE_ARRAY,
|
||||
.map_name = "array_map_check_btf",
|
||||
.key_size = sizeof(int),
|
||||
.value_size = sizeof(int),
|
||||
.key_type_id = 2,
|
||||
.value_type_id = 1,
|
||||
.max_entries = 4,
|
||||
.map_create_err = true,
|
||||
},
|
||||
|
||||
{
|
||||
.descr = "arraymap invalid btf key (!= 32 bits)",
|
||||
.raw_types = {
|
||||
/* int */ /* [1] */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
|
||||
/* 16 bit int with 0 bit offset */ /* [2] */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 16, 2),
|
||||
BTF_END_RAW,
|
||||
},
|
||||
.str_sec = "",
|
||||
.str_sec_size = sizeof(""),
|
||||
.map_type = BPF_MAP_TYPE_ARRAY,
|
||||
.map_name = "array_map_check_btf",
|
||||
.key_size = sizeof(int),
|
||||
.value_size = sizeof(int),
|
||||
.key_type_id = 2,
|
||||
.value_type_id = 1,
|
||||
.max_entries = 4,
|
||||
.map_create_err = true,
|
||||
},
|
||||
|
||||
{
|
||||
.descr = "arraymap invalid btf value (too small)",
|
||||
.raw_types = {
|
||||
/* int */ /* [1] */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
|
||||
BTF_END_RAW,
|
||||
},
|
||||
.str_sec = "",
|
||||
.str_sec_size = sizeof(""),
|
||||
.map_type = BPF_MAP_TYPE_ARRAY,
|
||||
.map_name = "array_map_check_btf",
|
||||
.key_size = sizeof(int),
|
||||
/* btf_value_size < map->value_size */
|
||||
.value_size = sizeof(__u64),
|
||||
.key_type_id = 1,
|
||||
.value_type_id = 1,
|
||||
.max_entries = 4,
|
||||
.map_create_err = true,
|
||||
},
|
||||
|
||||
{
|
||||
.descr = "arraymap invalid btf value (too big)",
|
||||
.raw_types = {
|
||||
/* int */ /* [1] */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
|
||||
BTF_END_RAW,
|
||||
},
|
||||
.str_sec = "",
|
||||
.str_sec_size = sizeof(""),
|
||||
.map_type = BPF_MAP_TYPE_ARRAY,
|
||||
.map_name = "array_map_check_btf",
|
||||
.key_size = sizeof(int),
|
||||
/* btf_value_size > map->value_size */
|
||||
.value_size = sizeof(__u16),
|
||||
.key_type_id = 1,
|
||||
.value_type_id = 1,
|
||||
.max_entries = 4,
|
||||
.map_create_err = true,
|
||||
},
|
||||
|
||||
}; /* struct btf_raw_test raw_tests[] */
|
||||
|
||||
static const char *get_next_str(const char *start, const char *end)
|
||||
@ -2023,7 +2133,7 @@ static struct btf_raw_test pprint_test = {
|
||||
BTF_ENUM_ENC(NAME_TBD, 2),
|
||||
BTF_ENUM_ENC(NAME_TBD, 3),
|
||||
/* struct pprint_mapv */ /* [16] */
|
||||
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 28),
|
||||
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 32),
|
||||
BTF_MEMBER_ENC(NAME_TBD, 11, 0), /* uint32_t ui32 */
|
||||
BTF_MEMBER_ENC(NAME_TBD, 10, 32), /* uint16_t ui16 */
|
||||
BTF_MEMBER_ENC(NAME_TBD, 12, 64), /* int32_t si32 */
|
||||
|
@ -10,11 +10,6 @@ struct ipv_counts {
|
||||
unsigned int v6;
|
||||
};
|
||||
|
||||
typedef int btf_map_key;
|
||||
typedef struct ipv_counts btf_map_value;
|
||||
btf_map_key dumm_key;
|
||||
btf_map_value dummy_value;
|
||||
|
||||
struct bpf_map_def SEC("maps") btf_map = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(int),
|
||||
@ -22,6 +17,8 @@ struct bpf_map_def SEC("maps") btf_map = {
|
||||
.max_entries = 4,
|
||||
};
|
||||
|
||||
BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
|
||||
|
||||
struct dummy_tracepoint_args {
|
||||
unsigned long long pad;
|
||||
struct sock *sock;
|
||||
|
Loading…
Reference in New Issue
Block a user