Skip to content

Commit 2472d76

Browse files
ebirgerdavem330
authored andcommitted
net: packet: use sockaddr_ll fields as storage for skb original length in recvmsg path
As part of an effort to move skb->dropcount to skb->cb[], 4 bytes of additional room are needed in skb->cb[] in packet sockets. Store the skb original length in the first two fields of sockaddr_ll (sll_family and sll_protocol) as they can be derived from the skb when needed. Signed-off-by: Eyal Birger <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2cfdf9f commit 2472d76

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

net/packet/af_packet.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,16 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *,
216216
static void packet_flush_mclist(struct sock *sk);
217217

218218
struct packet_skb_cb {
219-
unsigned int origlen;
220219
union {
221220
struct sockaddr_pkt pkt;
222-
struct sockaddr_ll ll;
221+
union {
222+
/* Trick: alias skb original length with
223+
* ll.sll_family and ll.protocol in order
224+
* to save room.
225+
*/
226+
unsigned int origlen;
227+
struct sockaddr_ll ll;
228+
};
223229
} sa;
224230
};
225231

@@ -1814,9 +1820,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
18141820
sizeof(skb->cb));
18151821

18161822
sll = &PACKET_SKB_CB(skb)->sa.ll;
1817-
sll->sll_family = AF_PACKET;
18181823
sll->sll_hatype = dev->type;
1819-
sll->sll_protocol = skb->protocol;
18201824
sll->sll_pkttype = skb->pkt_type;
18211825
if (unlikely(po->origdev))
18221826
sll->sll_ifindex = orig_dev->ifindex;
@@ -1825,7 +1829,10 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
18251829

18261830
sll->sll_halen = dev_parse_header(skb, sll->sll_addr);
18271831

1828-
PACKET_SKB_CB(skb)->origlen = skb->len;
1832+
/* sll->sll_family and sll->sll_protocol are set in packet_recvmsg().
1833+
* Use their space for storing the original skb length.
1834+
*/
1835+
PACKET_SKB_CB(skb)->sa.origlen = skb->len;
18291836

18301837
if (pskb_trim(skb, snaplen))
18311838
goto drop_n_acct;
@@ -2883,6 +2890,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
28832890
struct sk_buff *skb;
28842891
int copied, err;
28852892
int vnet_hdr_len = 0;
2893+
unsigned int origlen = 0;
28862894

28872895
err = -EINVAL;
28882896
if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT|MSG_ERRQUEUE))
@@ -2982,6 +2990,15 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
29822990
if (err)
29832991
goto out_free;
29842992

2993+
if (sock->type != SOCK_PACKET) {
2994+
struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
2995+
2996+
/* Original length was stored in sockaddr_ll fields */
2997+
origlen = PACKET_SKB_CB(skb)->sa.origlen;
2998+
sll->sll_family = AF_PACKET;
2999+
sll->sll_protocol = skb->protocol;
3000+
}
3001+
29853002
sock_recv_ts_and_drops(msg, sk, skb);
29863003

29873004
if (msg->msg_name) {
@@ -2993,6 +3010,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
29933010
msg->msg_namelen = sizeof(struct sockaddr_pkt);
29943011
} else {
29953012
struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
3013+
29963014
msg->msg_namelen = sll->sll_halen +
29973015
offsetof(struct sockaddr_ll, sll_addr);
29983016
}
@@ -3006,7 +3024,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
30063024
aux.tp_status = TP_STATUS_USER;
30073025
if (skb->ip_summed == CHECKSUM_PARTIAL)
30083026
aux.tp_status |= TP_STATUS_CSUMNOTREADY;
3009-
aux.tp_len = PACKET_SKB_CB(skb)->origlen;
3027+
aux.tp_len = origlen;
30103028
aux.tp_snaplen = skb->len;
30113029
aux.tp_mac = 0;
30123030
aux.tp_net = skb_network_offset(skb);

0 commit comments

Comments
 (0)