Skip to content

Commit cb820f8

Browse files
richardcochrandavem330
authored andcommitted
net: Provide a generic socket error queue delivery method for Tx time stamps.
This patch moves the private error queue delivery function from the af_packet code to the core socket method. In this way, network layers only needing the error queue for transmit time stamping can share common code. Signed-off-by: Richard Cochran <richardcochran@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 0887a57 commit cb820f8

File tree

3 files changed

+51
-46
lines changed

3 files changed

+51
-46
lines changed

include/net/sock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2249,6 +2249,8 @@ static inline struct sock *skb_steal_sock(struct sk_buff *skb)
22492249
extern void sock_enable_timestamp(struct sock *sk, int flag);
22502250
extern int sock_get_timestamp(struct sock *, struct timeval __user *);
22512251
extern int sock_get_timestampns(struct sock *, struct timespec __user *);
2252+
extern int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
2253+
int level, int type);
22522254

22532255
/*
22542256
* Enable debug/info messages

net/core/sock.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393

9494
#include <linux/capability.h>
9595
#include <linux/errno.h>
96+
#include <linux/errqueue.h>
9697
#include <linux/types.h>
9798
#include <linux/socket.h>
9899
#include <linux/in.h>
@@ -2425,6 +2426,52 @@ void sock_enable_timestamp(struct sock *sk, int flag)
24252426
}
24262427
}
24272428

2429+
int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
2430+
int level, int type)
2431+
{
2432+
struct sock_exterr_skb *serr;
2433+
struct sk_buff *skb, *skb2;
2434+
int copied, err;
2435+
2436+
err = -EAGAIN;
2437+
skb = skb_dequeue(&sk->sk_error_queue);
2438+
if (skb == NULL)
2439+
goto out;
2440+
2441+
copied = skb->len;
2442+
if (copied > len) {
2443+
msg->msg_flags |= MSG_TRUNC;
2444+
copied = len;
2445+
}
2446+
err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
2447+
if (err)
2448+
goto out_free_skb;
2449+
2450+
sock_recv_timestamp(msg, sk, skb);
2451+
2452+
serr = SKB_EXT_ERR(skb);
2453+
put_cmsg(msg, level, type, sizeof(serr->ee), &serr->ee);
2454+
2455+
msg->msg_flags |= MSG_ERRQUEUE;
2456+
err = copied;
2457+
2458+
/* Reset and regenerate socket error */
2459+
spin_lock_bh(&sk->sk_error_queue.lock);
2460+
sk->sk_err = 0;
2461+
if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) {
2462+
sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno;
2463+
spin_unlock_bh(&sk->sk_error_queue.lock);
2464+
sk->sk_error_report(sk);
2465+
} else
2466+
spin_unlock_bh(&sk->sk_error_queue.lock);
2467+
2468+
out_free_skb:
2469+
kfree_skb(skb);
2470+
out:
2471+
return err;
2472+
}
2473+
EXPORT_SYMBOL(sock_recv_errqueue);
2474+
24282475
/*
24292476
* Get a socket option on an socket.
24302477
*

net/packet/af_packet.c

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2638,51 +2638,6 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
26382638
return err;
26392639
}
26402640

2641-
static int packet_recv_error(struct sock *sk, struct msghdr *msg, int len)
2642-
{
2643-
struct sock_exterr_skb *serr;
2644-
struct sk_buff *skb, *skb2;
2645-
int copied, err;
2646-
2647-
err = -EAGAIN;
2648-
skb = skb_dequeue(&sk->sk_error_queue);
2649-
if (skb == NULL)
2650-
goto out;
2651-
2652-
copied = skb->len;
2653-
if (copied > len) {
2654-
msg->msg_flags |= MSG_TRUNC;
2655-
copied = len;
2656-
}
2657-
err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
2658-
if (err)
2659-
goto out_free_skb;
2660-
2661-
sock_recv_timestamp(msg, sk, skb);
2662-
2663-
serr = SKB_EXT_ERR(skb);
2664-
put_cmsg(msg, SOL_PACKET, PACKET_TX_TIMESTAMP,
2665-
sizeof(serr->ee), &serr->ee);
2666-
2667-
msg->msg_flags |= MSG_ERRQUEUE;
2668-
err = copied;
2669-
2670-
/* Reset and regenerate socket error */
2671-
spin_lock_bh(&sk->sk_error_queue.lock);
2672-
sk->sk_err = 0;
2673-
if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) {
2674-
sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno;
2675-
spin_unlock_bh(&sk->sk_error_queue.lock);
2676-
sk->sk_error_report(sk);
2677-
} else
2678-
spin_unlock_bh(&sk->sk_error_queue.lock);
2679-
2680-
out_free_skb:
2681-
kfree_skb(skb);
2682-
out:
2683-
return err;
2684-
}
2685-
26862641
/*
26872642
* Pull a packet from our receive queue and hand it to the user.
26882643
* If necessary we block.
@@ -2708,7 +2663,8 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
27082663
#endif
27092664

27102665
if (flags & MSG_ERRQUEUE) {
2711-
err = packet_recv_error(sk, msg, len);
2666+
err = sock_recv_errqueue(sk, msg, len,
2667+
SOL_PACKET, PACKET_TX_TIMESTAMP);
27122668
goto out;
27132669
}
27142670

0 commit comments

Comments
 (0)