brintos

brintos / linux-shallow public Read only

0
0
Text · 2.6 KiB · add0f5a Raw
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