Merge branch 'main' of ra.kernel.org:/pub/scm/linux/kernel/git/davem/net into main

Steffen Klassert says:

====================

1) Fix esp_output_tail_tcp() on unsupported ESPINTCP.
   From Hagar Hemdan.

2) Fix two bugs in the recently introduced SA direction separation.
   From Antony Antony.

3) Fix unregister netdevice hang on hardware offload. We had to add another
   list where skbs linked to that are unlinked from the lists (deleted)
   but not yet freed.

4) Fix netdev reference count imbalance in xfrm_state_find.
   From Jianbo Liu.

5) Call xfrm_dev_policy_delete when killingi them on offloaded policies.
   Jianbo Liu.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2024-07-15 12:43:46 +01:00
commit 250b8b86b6
2 changed files with 85 additions and 5 deletions

View File

@ -127,10 +127,8 @@ void xdp_unreg_mem_model(struct xdp_mem_info *mem)
return;
if (type == MEM_TYPE_PAGE_POOL) {
rcu_read_lock();
xa = rhashtable_lookup(mem_id_ht, &id, mem_id_rht_params);
xa = rhashtable_lookup_fast(mem_id_ht, &id, mem_id_rht_params);
page_pool_destroy(xa->page_pool);
rcu_read_unlock();
}
}
EXPORT_SYMBOL_GPL(xdp_unreg_mem_model);

View File

@ -538,6 +538,61 @@ static void *packet_current_frame(struct packet_sock *po,
return packet_lookup_frame(po, rb, rb->head, status);
}
static u16 vlan_get_tci(struct sk_buff *skb, struct net_device *dev)
{
u8 *skb_orig_data = skb->data;
int skb_orig_len = skb->len;
struct vlan_hdr vhdr, *vh;
unsigned int header_len;
if (!dev)
return 0;
/* In the SOCK_DGRAM scenario, skb data starts at the network
* protocol, which is after the VLAN headers. The outer VLAN
* header is at the hard_header_len offset in non-variable
* length link layer headers. If it's a VLAN device, the
* min_header_len should be used to exclude the VLAN header
* size.
*/
if (dev->min_header_len == dev->hard_header_len)
header_len = dev->hard_header_len;
else if (is_vlan_dev(dev))
header_len = dev->min_header_len;
else
return 0;
skb_push(skb, skb->data - skb_mac_header(skb));
vh = skb_header_pointer(skb, header_len, sizeof(vhdr), &vhdr);
if (skb_orig_data != skb->data) {
skb->data = skb_orig_data;
skb->len = skb_orig_len;
}
if (unlikely(!vh))
return 0;
return ntohs(vh->h_vlan_TCI);
}
static __be16 vlan_get_protocol_dgram(struct sk_buff *skb)
{
__be16 proto = skb->protocol;
if (unlikely(eth_type_vlan(proto))) {
u8 *skb_orig_data = skb->data;
int skb_orig_len = skb->len;
skb_push(skb, skb->data - skb_mac_header(skb));
proto = __vlan_get_protocol(skb, proto, NULL);
if (skb_orig_data != skb->data) {
skb->data = skb_orig_data;
skb->len = skb_orig_len;
}
}
return proto;
}
static void prb_del_retire_blk_timer(struct tpacket_kbdq_core *pkc)
{
del_timer_sync(&pkc->retire_blk_timer);
@ -1007,10 +1062,16 @@ static void prb_clear_rxhash(struct tpacket_kbdq_core *pkc,
static void prb_fill_vlan_info(struct tpacket_kbdq_core *pkc,
struct tpacket3_hdr *ppd)
{
struct packet_sock *po = container_of(pkc, struct packet_sock, rx_ring.prb_bdqc);
if (skb_vlan_tag_present(pkc->skb)) {
ppd->hv1.tp_vlan_tci = skb_vlan_tag_get(pkc->skb);
ppd->hv1.tp_vlan_tpid = ntohs(pkc->skb->vlan_proto);
ppd->tp_status = TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
} else if (unlikely(po->sk.sk_type == SOCK_DGRAM && eth_type_vlan(pkc->skb->protocol))) {
ppd->hv1.tp_vlan_tci = vlan_get_tci(pkc->skb, pkc->skb->dev);
ppd->hv1.tp_vlan_tpid = ntohs(pkc->skb->protocol);
ppd->tp_status = TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
} else {
ppd->hv1.tp_vlan_tci = 0;
ppd->hv1.tp_vlan_tpid = 0;
@ -2428,6 +2489,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
h.h2->tp_vlan_tci = skb_vlan_tag_get(skb);
h.h2->tp_vlan_tpid = ntohs(skb->vlan_proto);
status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
} else if (unlikely(sk->sk_type == SOCK_DGRAM && eth_type_vlan(skb->protocol))) {
h.h2->tp_vlan_tci = vlan_get_tci(skb, skb->dev);
h.h2->tp_vlan_tpid = ntohs(skb->protocol);
status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
} else {
h.h2->tp_vlan_tci = 0;
h.h2->tp_vlan_tpid = 0;
@ -2457,7 +2522,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
sll->sll_halen = dev_parse_header(skb, sll->sll_addr);
sll->sll_family = AF_PACKET;
sll->sll_hatype = dev->type;
sll->sll_protocol = skb->protocol;
sll->sll_protocol = (sk->sk_type == SOCK_DGRAM) ?
vlan_get_protocol_dgram(skb) : skb->protocol;
sll->sll_pkttype = skb->pkt_type;
if (unlikely(packet_sock_flag(po, PACKET_SOCK_ORIGDEV)))
sll->sll_ifindex = orig_dev->ifindex;
@ -3482,7 +3548,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
/* Original length was stored in sockaddr_ll fields */
origlen = PACKET_SKB_CB(skb)->sa.origlen;
sll->sll_family = AF_PACKET;
sll->sll_protocol = skb->protocol;
sll->sll_protocol = (sock->type == SOCK_DGRAM) ?
vlan_get_protocol_dgram(skb) : skb->protocol;
}
sock_recv_cmsgs(msg, sk, skb);
@ -3539,6 +3606,21 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
aux.tp_vlan_tci = skb_vlan_tag_get(skb);
aux.tp_vlan_tpid = ntohs(skb->vlan_proto);
aux.tp_status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
} else if (unlikely(sock->type == SOCK_DGRAM && eth_type_vlan(skb->protocol))) {
struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
struct net_device *dev;
rcu_read_lock();
dev = dev_get_by_index_rcu(sock_net(sk), sll->sll_ifindex);
if (dev) {
aux.tp_vlan_tci = vlan_get_tci(skb, dev);
aux.tp_vlan_tpid = ntohs(skb->protocol);
aux.tp_status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
} else {
aux.tp_vlan_tci = 0;
aux.tp_vlan_tpid = 0;
}
rcu_read_unlock();
} else {
aux.tp_vlan_tci = 0;
aux.tp_vlan_tpid = 0;