103 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* 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_map_header *map_header = (void *)skb->data;16 struct rmnet_endpoint *ep;17 struct net_device *vnd;18 u8 mux_id;19 int r;20 21 mux_id = map_header->mux_id;22 23 if (mux_id >= RMNET_MAX_LOGICAL_EP) {24 kfree_skb(skb);25 return RX_HANDLER_CONSUMED;26 }27 28 ep = rmnet_get_endpoint(port, mux_id);29 if (!ep) {30 kfree_skb(skb);31 return RX_HANDLER_CONSUMED;32 }33 34 vnd = ep->egress_dev;35 36 /* Ignore the ip family and pass the sequence number for both v4 and v637 * sequence. User space does not support creating dedicated flows for38 * the 2 protocols39 */40 r = rmnet_vnd_do_flow_control(vnd, enable);41 if (r) {42 kfree_skb(skb);43 return RMNET_MAP_COMMAND_UNSUPPORTED;44 } else {45 return RMNET_MAP_COMMAND_ACK;46 }47}48 49static void rmnet_map_send_ack(struct sk_buff *skb,50 unsigned char type,51 struct rmnet_port *port)52{53 struct rmnet_map_header *map_header = (void *)skb->data;54 struct rmnet_map_control_command *cmd;55 struct net_device *dev = skb->dev;56 57 if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4)58 skb_trim(skb,59 skb->len - sizeof(struct rmnet_map_dl_csum_trailer));60 61 skb->protocol = htons(ETH_P_MAP);62 63 /* Command data immediately follows the MAP header */64 cmd = (struct rmnet_map_control_command *)(map_header + 1);65 cmd->cmd_type = type & 0x03;66 67 netif_tx_lock(dev);68 dev->netdev_ops->ndo_start_xmit(skb, dev);69 netif_tx_unlock(dev);70}71 72/* Process MAP command frame and send N/ACK message as appropriate. Message cmd73 * name is decoded here and appropriate handler is called.74 */75void rmnet_map_command(struct sk_buff *skb, struct rmnet_port *port)76{77 struct rmnet_map_header *map_header = (void *)skb->data;78 struct rmnet_map_control_command *cmd;79 unsigned char command_name;80 unsigned char rc = 0;81 82 /* Command data immediately follows the MAP header */83 cmd = (struct rmnet_map_control_command *)(map_header + 1);84 command_name = cmd->command_name;85 86 switch (command_name) {87 case RMNET_MAP_COMMAND_FLOW_ENABLE:88 rc = rmnet_map_do_flow_control(skb, port, 1);89 break;90 91 case RMNET_MAP_COMMAND_FLOW_DISABLE:92 rc = rmnet_map_do_flow_control(skb, port, 0);93 break;94 95 default:96 rc = RMNET_MAP_COMMAND_UNSUPPORTED;97 kfree_skb(skb);98 break;99 }100 if (rc == RMNET_MAP_COMMAND_ACK)101 rmnet_map_send_ack(skb, rc, port);102}103