xref: /linux/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c (revision e83332842a46c091992ad06145b5c1b65a08ab05)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2013-2018, 2021, The Linux Foundation. All rights reserved.
3  *
4  * RMNET Data ingress/egress handler
5  */
6 
7 #include <linux/netdevice.h>
8 #include <linux/netdev_features.h>
9 #include <linux/if_arp.h>
10 #include <net/sock.h>
11 #include "rmnet_private.h"
12 #include "rmnet_config.h"
13 #include "rmnet_vnd.h"
14 #include "rmnet_map.h"
15 #include "rmnet_handlers.h"
16 
17 #define RMNET_IP_VERSION_4 0x40
18 #define RMNET_IP_VERSION_6 0x60
19 
20 /* Helper Functions */
21 
22 static void rmnet_set_skb_proto(struct sk_buff *skb)
23 {
24 	switch (skb->data[0] & 0xF0) {
25 	case RMNET_IP_VERSION_4:
26 		skb->protocol = htons(ETH_P_IP);
27 		break;
28 	case RMNET_IP_VERSION_6:
29 		skb->protocol = htons(ETH_P_IPV6);
30 		break;
31 	default:
32 		skb->protocol = htons(ETH_P_MAP);
33 		break;
34 	}
35 }
36 
37 /* Generic handler */
38 
39 static void
40 rmnet_deliver_skb(struct sk_buff *skb)
41 {
42 	struct rmnet_priv *priv = netdev_priv(skb->dev);
43 
44 	skb_reset_transport_header(skb);
45 	skb_reset_network_header(skb);
46 	rmnet_vnd_rx_fixup(skb, skb->dev);
47 
48 	skb->pkt_type = PACKET_HOST;
49 	skb_set_mac_header(skb, 0);
50 	gro_cells_receive(&priv->gro_cells, skb);
51 }
52 
53 /* MAP handler */
54 
55 static void
56 __rmnet_map_ingress_handler(struct sk_buff *skb,
57 			    struct rmnet_port *port)
58 {
59 	struct rmnet_map_header *map_header = (void *)skb->data;
60 	struct rmnet_endpoint *ep;
61 	u16 len, pad;
62 	u8 mux_id;
63 
64 	if (map_header->flags & MAP_CMD_FLAG) {
65 		/* Packet contains a MAP command (not data) */
66 		if (port->data_format & RMNET_FLAGS_INGRESS_MAP_COMMANDS)
67 			return rmnet_map_command(skb, port);
68 
69 		goto free_skb;
70 	}
71 
72 	mux_id = map_header->mux_id;
73 	pad = map_header->flags & MAP_PAD_LEN_MASK;
74 	len = ntohs(map_header->pkt_len) - pad;
75 
76 	if (mux_id >= RMNET_MAX_LOGICAL_EP)
77 		goto free_skb;
78 
79 	ep = rmnet_get_endpoint(port, mux_id);
80 	if (!ep)
81 		goto free_skb;
82 
83 	skb->dev = ep->egress_dev;
84 
85 	if ((port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV5) &&
86 	    (map_header->flags & MAP_NEXT_HEADER_FLAG)) {
87 		if (rmnet_map_process_next_hdr_packet(skb, len))
88 			goto free_skb;
89 		skb_pull(skb, sizeof(*map_header));
90 		rmnet_set_skb_proto(skb);
91 	} else if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) {
92 		/* Subtract MAP header */
93 		skb_pull(skb, sizeof(*map_header));
94 		rmnet_set_skb_proto(skb);
95 		if (!rmnet_map_checksum_downlink_packet(skb, len + pad))
96 			skb->ip_summed = CHECKSUM_UNNECESSARY;
97 	}
98 
99 	skb_trim(skb, len);
100 	rmnet_deliver_skb(skb);
101 	return;
102 
103 free_skb:
104 	kfree_skb(skb);
105 }
106 
107 static void
108 rmnet_map_ingress_handler(struct sk_buff *skb,
109 			  struct rmnet_port *port)
110 {
111 	struct sk_buff *skbn;
112 
113 	if (skb->dev->type == ARPHRD_ETHER) {
114 		if (pskb_expand_head(skb, ETH_HLEN, 0, GFP_ATOMIC)) {
115 			kfree_skb(skb);
116 			return;
117 		}
118 
119 		skb_push(skb, ETH_HLEN);
120 	}
121 
122 	if (port->data_format & RMNET_FLAGS_INGRESS_DEAGGREGATION) {
123 		while ((skbn = rmnet_map_deaggregate(skb, port)) != NULL)
124 			__rmnet_map_ingress_handler(skbn, port);
125 
126 		consume_skb(skb);
127 	} else {
128 		__rmnet_map_ingress_handler(skb, port);
129 	}
130 }
131 
132 static int rmnet_map_egress_handler(struct sk_buff *skb,
133 				    struct rmnet_port *port, u8 mux_id,
134 				    struct net_device *orig_dev)
135 {
136 	int required_headroom, additional_header_len, csum_type = 0;
137 	struct rmnet_map_header *map_header;
138 
139 	additional_header_len = 0;
140 	required_headroom = sizeof(struct rmnet_map_header);
141 
142 	if (port->data_format & RMNET_FLAGS_EGRESS_MAP_CKSUMV4) {
143 		additional_header_len = sizeof(struct rmnet_map_ul_csum_header);
144 		csum_type = RMNET_FLAGS_EGRESS_MAP_CKSUMV4;
145 	} else if (port->data_format & RMNET_FLAGS_EGRESS_MAP_CKSUMV5) {
146 		additional_header_len = sizeof(struct rmnet_map_v5_csum_header);
147 		csum_type = RMNET_FLAGS_EGRESS_MAP_CKSUMV5;
148 	}
149 
150 	required_headroom += additional_header_len;
151 
152 	if (skb_cow_head(skb, required_headroom) < 0)
153 		return -ENOMEM;
154 
155 	if (csum_type)
156 		rmnet_map_checksum_uplink_packet(skb, port, orig_dev,
157 						 csum_type);
158 
159 	map_header = rmnet_map_add_map_header(skb, additional_header_len,
160 					      port, 0);
161 	if (!map_header)
162 		return -ENOMEM;
163 
164 	map_header->mux_id = mux_id;
165 
166 	skb->protocol = htons(ETH_P_MAP);
167 
168 	return 0;
169 }
170 
171 static void
172 rmnet_bridge_handler(struct sk_buff *skb, struct net_device *bridge_dev)
173 {
174 	if (skb_mac_header_was_set(skb))
175 		skb_push(skb, skb->mac_len);
176 
177 	if (bridge_dev) {
178 		skb->dev = bridge_dev;
179 		dev_queue_xmit(skb);
180 	}
181 }
182 
183 /* Ingress / Egress Entry Points */
184 
185 /* Processes packet as per ingress data format for receiving device. Logical
186  * endpoint is determined from packet inspection. Packet is then sent to the
187  * egress device listed in the logical endpoint configuration.
188  */
189 rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb)
190 {
191 	struct sk_buff *skb = *pskb;
192 	struct rmnet_port *port;
193 	struct net_device *dev;
194 
195 	if (!skb)
196 		goto done;
197 
198 	if (skb_linearize(skb)) {
199 		kfree_skb(skb);
200 		goto done;
201 	}
202 
203 	if (skb->pkt_type == PACKET_LOOPBACK)
204 		return RX_HANDLER_PASS;
205 
206 	dev = skb->dev;
207 	port = rmnet_get_port_rcu(dev);
208 	if (unlikely(!port)) {
209 		atomic_long_inc(&skb->dev->rx_nohandler);
210 		kfree_skb(skb);
211 		goto done;
212 	}
213 
214 	switch (port->rmnet_mode) {
215 	case RMNET_EPMODE_VND:
216 		rmnet_map_ingress_handler(skb, port);
217 		break;
218 	case RMNET_EPMODE_BRIDGE:
219 		rmnet_bridge_handler(skb, port->bridge_ep);
220 		break;
221 	}
222 
223 done:
224 	return RX_HANDLER_CONSUMED;
225 }
226 
227 /* Modifies packet as per logical endpoint configuration and egress data format
228  * for egress device configured in logical endpoint. Packet is then transmitted
229  * on the egress device.
230  */
231 void rmnet_egress_handler(struct sk_buff *skb)
232 {
233 	struct net_device *orig_dev;
234 	struct rmnet_port *port;
235 	struct rmnet_priv *priv;
236 	u8 mux_id;
237 
238 	sk_pacing_shift_update(skb->sk, 8);
239 
240 	orig_dev = skb->dev;
241 	priv = netdev_priv(orig_dev);
242 	skb->dev = priv->real_dev;
243 	mux_id = priv->mux_id;
244 
245 	port = rmnet_get_port_rcu(skb->dev);
246 	if (!port)
247 		goto drop;
248 
249 	if (rmnet_map_egress_handler(skb, port, mux_id, orig_dev))
250 		goto drop;
251 
252 	rmnet_vnd_tx_fixup(skb, orig_dev);
253 
254 	dev_queue_xmit(skb);
255 	return;
256 
257 drop:
258 	this_cpu_inc(priv->pcpu_stats->stats.tx_drops);
259 	kfree_skb(skb);
260 }
261