1 /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * RMNET Data ingress/egress handler
16 #include <linux/netdevice.h>
17 #include <linux/netdev_features.h>
18 #include <linux/if_arp.h>
20 #include "rmnet_private.h"
21 #include "rmnet_config.h"
22 #include "rmnet_vnd.h"
23 #include "rmnet_map.h"
24 #include "rmnet_handlers.h"
26 #define RMNET_IP_VERSION_4 0x40
27 #define RMNET_IP_VERSION_6 0x60
29 /* Helper Functions */
31 static void rmnet_set_skb_proto(struct sk_buff
*skb
)
33 switch (skb
->data
[0] & 0xF0) {
34 case RMNET_IP_VERSION_4
:
35 skb
->protocol
= htons(ETH_P_IP
);
37 case RMNET_IP_VERSION_6
:
38 skb
->protocol
= htons(ETH_P_IPV6
);
41 skb
->protocol
= htons(ETH_P_MAP
);
49 rmnet_deliver_skb(struct sk_buff
*skb
)
51 struct rmnet_priv
*priv
= netdev_priv(skb
->dev
);
53 skb_reset_transport_header(skb
);
54 skb_reset_network_header(skb
);
55 rmnet_vnd_rx_fixup(skb
, skb
->dev
);
57 skb
->pkt_type
= PACKET_HOST
;
58 skb_set_mac_header(skb
, 0);
59 gro_cells_receive(&priv
->gro_cells
, skb
);
65 __rmnet_map_ingress_handler(struct sk_buff
*skb
,
66 struct rmnet_port
*port
)
68 struct rmnet_endpoint
*ep
;
72 if (RMNET_MAP_GET_CD_BIT(skb
)) {
73 if (port
->data_format
& RMNET_INGRESS_FORMAT_MAP_COMMANDS
)
74 return rmnet_map_command(skb
, port
);
79 mux_id
= RMNET_MAP_GET_MUX_ID(skb
);
80 pad
= RMNET_MAP_GET_PAD(skb
);
81 len
= RMNET_MAP_GET_LENGTH(skb
) - pad
;
83 if (mux_id
>= RMNET_MAX_LOGICAL_EP
)
86 ep
= rmnet_get_endpoint(port
, mux_id
);
90 skb
->dev
= ep
->egress_dev
;
92 /* Subtract MAP header */
93 skb_pull(skb
, sizeof(struct rmnet_map_header
));
94 rmnet_set_skb_proto(skb
);
96 if (port
->data_format
& RMNET_INGRESS_FORMAT_MAP_CKSUMV4
) {
97 if (!rmnet_map_checksum_downlink_packet(skb
, len
+ pad
))
98 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
102 rmnet_deliver_skb(skb
);
110 rmnet_map_ingress_handler(struct sk_buff
*skb
,
111 struct rmnet_port
*port
)
113 struct sk_buff
*skbn
;
115 if (skb
->dev
->type
== ARPHRD_ETHER
) {
116 if (pskb_expand_head(skb
, ETH_HLEN
, 0, GFP_KERNEL
)) {
121 skb_push(skb
, ETH_HLEN
);
124 if (port
->data_format
& RMNET_INGRESS_FORMAT_DEAGGREGATION
) {
125 while ((skbn
= rmnet_map_deaggregate(skb
, port
)) != NULL
)
126 __rmnet_map_ingress_handler(skbn
, port
);
130 __rmnet_map_ingress_handler(skb
, port
);
134 static int rmnet_map_egress_handler(struct sk_buff
*skb
,
135 struct rmnet_port
*port
, u8 mux_id
,
136 struct net_device
*orig_dev
)
138 int required_headroom
, additional_header_len
;
139 struct rmnet_map_header
*map_header
;
141 additional_header_len
= 0;
142 required_headroom
= sizeof(struct rmnet_map_header
);
144 if (port
->data_format
& RMNET_EGRESS_FORMAT_MAP_CKSUMV4
) {
145 additional_header_len
= sizeof(struct rmnet_map_ul_csum_header
);
146 required_headroom
+= additional_header_len
;
149 if (skb_headroom(skb
) < required_headroom
) {
150 if (pskb_expand_head(skb
, required_headroom
, 0, GFP_KERNEL
))
154 if (port
->data_format
& RMNET_EGRESS_FORMAT_MAP_CKSUMV4
)
155 rmnet_map_checksum_uplink_packet(skb
, orig_dev
);
157 map_header
= rmnet_map_add_map_header(skb
, additional_header_len
, 0);
161 map_header
->mux_id
= mux_id
;
163 skb
->protocol
= htons(ETH_P_MAP
);
173 rmnet_bridge_handler(struct sk_buff
*skb
, struct net_device
*bridge_dev
)
176 skb
->dev
= bridge_dev
;
181 /* Ingress / Egress Entry Points */
183 /* Processes packet as per ingress data format for receiving device. Logical
184 * endpoint is determined from packet inspection. Packet is then sent to the
185 * egress device listed in the logical endpoint configuration.
187 rx_handler_result_t
rmnet_rx_handler(struct sk_buff
**pskb
)
189 struct sk_buff
*skb
= *pskb
;
190 struct rmnet_port
*port
;
191 struct net_device
*dev
;
197 port
= rmnet_get_port(dev
);
199 switch (port
->rmnet_mode
) {
200 case RMNET_EPMODE_VND
:
201 rmnet_map_ingress_handler(skb
, port
);
203 case RMNET_EPMODE_BRIDGE
:
204 rmnet_bridge_handler(skb
, port
->bridge_ep
);
209 return RX_HANDLER_CONSUMED
;
212 /* Modifies packet as per logical endpoint configuration and egress data format
213 * for egress device configured in logical endpoint. Packet is then transmitted
214 * on the egress device.
216 void rmnet_egress_handler(struct sk_buff
*skb
)
218 struct net_device
*orig_dev
;
219 struct rmnet_port
*port
;
220 struct rmnet_priv
*priv
;
223 sk_pacing_shift_update(skb
->sk
, 8);
226 priv
= netdev_priv(orig_dev
);
227 skb
->dev
= priv
->real_dev
;
228 mux_id
= priv
->mux_id
;
230 port
= rmnet_get_port(skb
->dev
);
236 if (rmnet_map_egress_handler(skb
, port
, mux_id
, orig_dev
))
239 rmnet_vnd_tx_fixup(skb
, orig_dev
);