0001
0002
0003
0004
0005 #include <linux/netdevice.h>
0006 #include "rmnet_config.h"
0007 #include "rmnet_map.h"
0008 #include "rmnet_private.h"
0009 #include "rmnet_vnd.h"
0010
0011 static u8 rmnet_map_do_flow_control(struct sk_buff *skb,
0012 struct rmnet_port *port,
0013 int enable)
0014 {
0015 struct rmnet_map_header *map_header = (void *)skb->data;
0016 struct rmnet_endpoint *ep;
0017 struct net_device *vnd;
0018 u8 mux_id;
0019 int r;
0020
0021 mux_id = map_header->mux_id;
0022
0023 if (mux_id >= RMNET_MAX_LOGICAL_EP) {
0024 kfree_skb(skb);
0025 return RX_HANDLER_CONSUMED;
0026 }
0027
0028 ep = rmnet_get_endpoint(port, mux_id);
0029 if (!ep) {
0030 kfree_skb(skb);
0031 return RX_HANDLER_CONSUMED;
0032 }
0033
0034 vnd = ep->egress_dev;
0035
0036
0037
0038
0039
0040 r = rmnet_vnd_do_flow_control(vnd, enable);
0041 if (r) {
0042 kfree_skb(skb);
0043 return RMNET_MAP_COMMAND_UNSUPPORTED;
0044 } else {
0045 return RMNET_MAP_COMMAND_ACK;
0046 }
0047 }
0048
0049 static void rmnet_map_send_ack(struct sk_buff *skb,
0050 unsigned char type,
0051 struct rmnet_port *port)
0052 {
0053 struct rmnet_map_header *map_header = (void *)skb->data;
0054 struct rmnet_map_control_command *cmd;
0055 struct net_device *dev = skb->dev;
0056
0057 if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4)
0058 skb_trim(skb,
0059 skb->len - sizeof(struct rmnet_map_dl_csum_trailer));
0060
0061 skb->protocol = htons(ETH_P_MAP);
0062
0063
0064 cmd = (struct rmnet_map_control_command *)(map_header + 1);
0065 cmd->cmd_type = type & 0x03;
0066
0067 netif_tx_lock(dev);
0068 dev->netdev_ops->ndo_start_xmit(skb, dev);
0069 netif_tx_unlock(dev);
0070 }
0071
0072
0073
0074
0075 void rmnet_map_command(struct sk_buff *skb, struct rmnet_port *port)
0076 {
0077 struct rmnet_map_header *map_header = (void *)skb->data;
0078 struct rmnet_map_control_command *cmd;
0079 unsigned char command_name;
0080 unsigned char rc = 0;
0081
0082
0083 cmd = (struct rmnet_map_control_command *)(map_header + 1);
0084 command_name = cmd->command_name;
0085
0086 switch (command_name) {
0087 case RMNET_MAP_COMMAND_FLOW_ENABLE:
0088 rc = rmnet_map_do_flow_control(skb, port, 1);
0089 break;
0090
0091 case RMNET_MAP_COMMAND_FLOW_DISABLE:
0092 rc = rmnet_map_do_flow_control(skb, port, 0);
0093 break;
0094
0095 default:
0096 rc = RMNET_MAP_COMMAND_UNSUPPORTED;
0097 kfree_skb(skb);
0098 break;
0099 }
0100 if (rc == RMNET_MAP_COMMAND_ACK)
0101 rmnet_map_send_ack(skb, rc, port);
0102 }