aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/patches-4.1/630-packet_socket_type.patch
blob: ca6ce297c49e644b15746c11e5de5d6b148b85e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
This patch allows the user to specify desired packet types (outgoing,
broadcast, unicast, etc.) on packet sockets via setsockopt.
This can reduce the load in situations where only a limited number
of packet types are necessary

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

--- a/include/uapi/linux/if_packet.h
+++ b/include/uapi/linux/if_packet.h
@@ -31,6 +31,8 @@ struct sockaddr_ll {
 #define PACKET_KERNEL		7		/* To kernel space	*/
 /* Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space */
 #define PACKET_FASTROUTE	6		/* Fastrouted frame	*/
+#define PACKET_MASK_ANY		0xffffffff	/* mask for packet type bits */
+
 
 /* Packet socket options */
 
@@ -54,6 +56,7 @@ struct sockaddr_ll {
 #define PACKET_FANOUT			18
 #define PACKET_TX_HAS_OFF		19
 #define PACKET_QDISC_BYPASS		20
+#define PACKET_RECV_TYPE		21
 
 #define PACKET_FANOUT_HASH		0
 #define PACKET_FANOUT_LB		1
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1533,6 +1533,7 @@ static int packet_rcv_spkt(struct sk_buf
 {
 	struct sock *sk;
 	struct sockaddr_pkt *spkt;
+	struct packet_sock *po;
 
 	/*
 	 *	When we registered the protocol we saved the socket in the data
@@ -1540,6 +1541,7 @@ static int packet_rcv_spkt(struct sk_buf
 	 */
 
 	sk = pt->af_packet_priv;
+	po = pkt_sk(sk);
 
 	/*
 	 *	Yank back the headers [hope the device set this
@@ -1552,7 +1554,7 @@ static int packet_rcv_spkt(struct sk_buf
 	 *	so that this procedure is noop.
 	 */
 
-	if (skb->pkt_type == PACKET_LOOPBACK)
+	if (!(po->pkt_type & (1 << skb->pkt_type)))
 		goto out;
 
 	if (!net_eq(dev_net(dev), sock_net(sk)))
@@ -1759,12 +1761,12 @@ static int packet_rcv(struct sk_buff *sk
 	int skb_len = skb->len;
 	unsigned int snaplen, res;
 
-	if (skb->pkt_type == PACKET_LOOPBACK)
-		goto drop;
-
 	sk = pt->af_packet_priv;
 	po = pkt_sk(sk);
 
+	if (!(po->pkt_type & (1 << skb->pkt_type)))
+		goto drop;
+
 	if (!net_eq(dev_net(dev), sock_net(sk)))
 		goto drop;
 
@@ -1884,12 +1886,12 @@ static int tpacket_rcv(struct sk_buff *s
 	BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32);
 	BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48);
 
-	if (skb->pkt_type == PACKET_LOOPBACK)
-		goto drop;
-
 	sk = pt->af_packet_priv;
 	po = pkt_sk(sk);
 
+	if (!(po->pkt_type & (1 << skb->pkt_type)))
+		goto drop;
+
 	if (!net_eq(dev_net(dev), sock_net(sk)))
 		goto drop;
 
@@ -2851,6 +2853,7 @@ static int packet_create(struct net *net
 	spin_lock_init(&po->bind_lock);
 	mutex_init(&po->pg_vec_lock);
 	po->prot_hook.func = packet_rcv;
+	po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK);
 
 	if (sock->type == SOCK_PACKET)
 		po->prot_hook.func = packet_rcv_spkt;
@@ -3456,6 +3459,16 @@ packet_setsockopt(struct socket *sock, i
 		po->xmit = val ? packet_direct_xmit : dev_queue_xmit;
 		return 0;
 	}
+        case PACKET_RECV_TYPE:
+        {
+                unsigned int val;
+                if (optlen != sizeof(val))
+                        return -EINVAL;
+                if (copy_from_user(&val, optval, sizeof(val)))
+                        return -EFAULT;
+                po->pkt_type = val & ~BIT(PACKET_LOOPBACK);
+                return 0;
+        }
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -3507,6 +3520,13 @@ static int packet_getsockopt(struct sock
 	case PACKET_VNET_HDR:
 		val = po->has_vnet_hdr;
 		break;
+	case PACKET_RECV_TYPE:
+		if (len > sizeof(unsigned int))
+			len = sizeof(unsigned int);
+		val = po->pkt_type;
+
+		data = &val;
+		break;
 	case PACKET_VERSION:
 		val = po->tp_version;
 		break;
--- a/net/packet/internal.h
+++ b/net/packet/internal.h
@@ -115,6 +115,7 @@ struct packet_sock {
 	struct net_device __rcu	*cached_dev;
 	int			(*xmit)(struct sk_buff *skb);
 	struct packet_type	prot_hook ____cacheline_aligned_in_smp;
+	unsigned int		pkt_type;
 };
 
 static struct packet_sock *pkt_sk(struct sock *sk)
BCM6362_RESET_PCIE_EXT SOFTRESET_6362_PCIE_EXT_MASK +#define BCM6362_RESET_PCIE_CORE SOFTRESET_6362_PCIE_CORE_MASK +#define BCM6362_RESET_PCIE_HARD 0 #define BCM6368_RESET_SPI SOFTRESET_6368_SPI_MASK #define BCM6368_RESET_ENET 0 @@ -141,6 +150,8 @@ #define BCM6368_RESET_MPI SOFTRESET_6368_MPI_MASK #define BCM6368_RESET_PCIE 0 #define BCM6368_RESET_PCIE_EXT 0 +#define BCM6368_RESET_PCIE_CORE 0 +#define BCM6368_RESET_PCIE_HARD 0 #define BCM63268_RESET_SPI SOFTRESET_63268_SPI_MASK #define BCM63268_RESET_ENET 0 @@ -152,10 +163,10 @@ #define BCM63268_RESET_ENETSW SOFTRESET_63268_ENETSW_MASK #define BCM63268_RESET_PCM SOFTRESET_63268_PCM_MASK #define BCM63268_RESET_MPI 0 -#define BCM63268_RESET_PCIE (SOFTRESET_63268_PCIE_MASK | \ - SOFTRESET_63268_PCIE_CORE_MASK | \ - SOFTRESET_63268_PCIE_HARD_MASK) +#define BCM63268_RESET_PCIE SOFTRESET_63268_PCIE_MASK #define BCM63268_RESET_PCIE_EXT SOFTRESET_63268_PCIE_EXT_MASK +#define BCM63268_RESET_PCIE_CORE SOFTRESET_63268_PCIE_CORE_MASK +#define BCM63268_RESET_PCIE_HARD SOFTRESET_63268_PCIE_HARD_MASK /* * core reset bits --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_reset.h @@ -14,6 +14,8 @@ enum bcm63xx_core_reset { BCM63XX_RESET_MPI, BCM63XX_RESET_PCIE, BCM63XX_RESET_PCIE_EXT, + BCM63XX_RESET_PCIE_CORE, + BCM63XX_RESET_PCIE_HARD, }; void bcm63xx_core_set_reset(enum bcm63xx_core_reset, int reset); --- a/arch/mips/pci/pci-bcm63xx.c +++ b/arch/mips/pci/pci-bcm63xx.c @@ -135,9 +135,16 @@ static void __init bcm63xx_reset_pcie(vo /* reset the PCIe core */ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 1); + bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_CORE, 1); bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 1); + if (BCMCPU_IS_6328() || BCMCPU_IS_63268()) { + bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_HARD, 1); + mdelay(10); + bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_HARD, 0); + } mdelay(10); + bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_CORE, 0); bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 0); mdelay(10);