at v5.2 97 lines 2.3 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. 3 */ 4 5#include <linux/netdevice.h> 6#include "rmnet_config.h" 7#include "rmnet_map.h" 8#include "rmnet_private.h" 9#include "rmnet_vnd.h" 10 11static u8 rmnet_map_do_flow_control(struct sk_buff *skb, 12 struct rmnet_port *port, 13 int enable) 14{ 15 struct rmnet_endpoint *ep; 16 struct net_device *vnd; 17 u8 mux_id; 18 int r; 19 20 mux_id = RMNET_MAP_GET_MUX_ID(skb); 21 22 if (mux_id >= RMNET_MAX_LOGICAL_EP) { 23 kfree_skb(skb); 24 return RX_HANDLER_CONSUMED; 25 } 26 27 ep = rmnet_get_endpoint(port, mux_id); 28 if (!ep) { 29 kfree_skb(skb); 30 return RX_HANDLER_CONSUMED; 31 } 32 33 vnd = ep->egress_dev; 34 35 /* Ignore the ip family and pass the sequence number for both v4 and v6 36 * sequence. User space does not support creating dedicated flows for 37 * the 2 protocols 38 */ 39 r = rmnet_vnd_do_flow_control(vnd, enable); 40 if (r) { 41 kfree_skb(skb); 42 return RMNET_MAP_COMMAND_UNSUPPORTED; 43 } else { 44 return RMNET_MAP_COMMAND_ACK; 45 } 46} 47 48static void rmnet_map_send_ack(struct sk_buff *skb, 49 unsigned char type, 50 struct rmnet_port *port) 51{ 52 struct rmnet_map_control_command *cmd; 53 struct net_device *dev = skb->dev; 54 55 if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) 56 skb_trim(skb, 57 skb->len - sizeof(struct rmnet_map_dl_csum_trailer)); 58 59 skb->protocol = htons(ETH_P_MAP); 60 61 cmd = RMNET_MAP_GET_CMD_START(skb); 62 cmd->cmd_type = type & 0x03; 63 64 netif_tx_lock(dev); 65 dev->netdev_ops->ndo_start_xmit(skb, dev); 66 netif_tx_unlock(dev); 67} 68 69/* Process MAP command frame and send N/ACK message as appropriate. Message cmd 70 * name is decoded here and appropriate handler is called. 71 */ 72void rmnet_map_command(struct sk_buff *skb, struct rmnet_port *port) 73{ 74 struct rmnet_map_control_command *cmd; 75 unsigned char command_name; 76 unsigned char rc = 0; 77 78 cmd = RMNET_MAP_GET_CMD_START(skb); 79 command_name = cmd->command_name; 80 81 switch (command_name) { 82 case RMNET_MAP_COMMAND_FLOW_ENABLE: 83 rc = rmnet_map_do_flow_control(skb, port, 1); 84 break; 85 86 case RMNET_MAP_COMMAND_FLOW_DISABLE: 87 rc = rmnet_map_do_flow_control(skb, port, 0); 88 break; 89 90 default: 91 rc = RMNET_MAP_COMMAND_UNSUPPORTED; 92 kfree_skb(skb); 93 break; 94 } 95 if (rc == RMNET_MAP_COMMAND_ACK) 96 rmnet_map_send_ack(skb, rc, port); 97}