Linux Audio

Check our new training course

Loading...
v4.17
 
  1/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  2 *
  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.
  6 *
  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.
 11 */
 12
 13#include <linux/netdevice.h>
 14#include "rmnet_config.h"
 15#include "rmnet_map.h"
 16#include "rmnet_private.h"
 17#include "rmnet_vnd.h"
 18
 19static u8 rmnet_map_do_flow_control(struct sk_buff *skb,
 20				    struct rmnet_port *port,
 21				    int enable)
 22{
 23	struct rmnet_map_control_command *cmd;
 24	struct rmnet_endpoint *ep;
 25	struct net_device *vnd;
 26	u16 ip_family;
 27	u16 fc_seq;
 28	u32 qos_id;
 29	u8 mux_id;
 30	int r;
 31
 32	mux_id = RMNET_MAP_GET_MUX_ID(skb);
 33	cmd = RMNET_MAP_GET_CMD_START(skb);
 34
 35	if (mux_id >= RMNET_MAX_LOGICAL_EP) {
 36		kfree_skb(skb);
 37		return RX_HANDLER_CONSUMED;
 38	}
 39
 40	ep = rmnet_get_endpoint(port, mux_id);
 41	if (!ep) {
 42		kfree_skb(skb);
 43		return RX_HANDLER_CONSUMED;
 44	}
 45
 46	vnd = ep->egress_dev;
 47
 48	ip_family = cmd->flow_control.ip_family;
 49	fc_seq = ntohs(cmd->flow_control.flow_control_seq_num);
 50	qos_id = ntohl(cmd->flow_control.qos_id);
 51
 52	/* Ignore the ip family and pass the sequence number for both v4 and v6
 53	 * sequence. User space does not support creating dedicated flows for
 54	 * the 2 protocols
 55	 */
 56	r = rmnet_vnd_do_flow_control(vnd, enable);
 57	if (r) {
 58		kfree_skb(skb);
 59		return RMNET_MAP_COMMAND_UNSUPPORTED;
 60	} else {
 61		return RMNET_MAP_COMMAND_ACK;
 62	}
 63}
 64
 65static void rmnet_map_send_ack(struct sk_buff *skb,
 66			       unsigned char type,
 67			       struct rmnet_port *port)
 68{
 
 69	struct rmnet_map_control_command *cmd;
 70	int xmit_status;
 71
 72	if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) {
 73		if (skb->len < sizeof(struct rmnet_map_header) +
 74		    RMNET_MAP_GET_LENGTH(skb) +
 75		    sizeof(struct rmnet_map_dl_csum_trailer)) {
 76			kfree_skb(skb);
 77			return;
 78		}
 79
 80		skb_trim(skb, skb->len -
 81			 sizeof(struct rmnet_map_dl_csum_trailer));
 82	}
 83
 84	skb->protocol = htons(ETH_P_MAP);
 85
 86	cmd = RMNET_MAP_GET_CMD_START(skb);
 
 87	cmd->cmd_type = type & 0x03;
 88
 89	netif_tx_lock(skb->dev);
 90	xmit_status = skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev);
 91	netif_tx_unlock(skb->dev);
 92}
 93
 94/* Process MAP command frame and send N/ACK message as appropriate. Message cmd
 95 * name is decoded here and appropriate handler is called.
 96 */
 97void rmnet_map_command(struct sk_buff *skb, struct rmnet_port *port)
 98{
 
 99	struct rmnet_map_control_command *cmd;
100	unsigned char command_name;
101	unsigned char rc = 0;
102
103	cmd = RMNET_MAP_GET_CMD_START(skb);
 
104	command_name = cmd->command_name;
105
106	switch (command_name) {
107	case RMNET_MAP_COMMAND_FLOW_ENABLE:
108		rc = rmnet_map_do_flow_control(skb, port, 1);
109		break;
110
111	case RMNET_MAP_COMMAND_FLOW_DISABLE:
112		rc = rmnet_map_do_flow_control(skb, port, 0);
113		break;
114
115	default:
116		rc = RMNET_MAP_COMMAND_UNSUPPORTED;
117		kfree_skb(skb);
118		break;
119	}
120	if (rc == RMNET_MAP_COMMAND_ACK)
121		rmnet_map_send_ack(skb, rc, port);
122}
v6.2
  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}