cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rmnet_map_command.c (2615B)


      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_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 v6
     37	 * sequence. User space does not support creating dedicated flows for
     38	 * the 2 protocols
     39	 */
     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 cmd
     73 * 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}