diff options
| author | Harout Hedeshian <harouth@codeaurora.org> | 2013-10-24 09:28:22 -0600 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:04:58 -0700 |
| commit | 3a9fa2aa8025735dcbf413d02ac694fd636f21f5 (patch) | |
| tree | 828d05b792c5566ca5db15821cba66d3344f3c4e /net/rmnet_data/rmnet_map_command.c | |
| parent | 162318ea3eec2d52f7f46752fb3be10541953289 (diff) | |
net: rmnet_data: In-band flow control
Implement MAP based in-band flow control. Added 2 new configuration
messages to allow adding and deleting flow handles. Added handlers
in VND for flow control events. Added flow control command handler
in rmnet_map_commands.
CRs-fixed: 568534
Change-Id: Ica52e4ad89430c9fa5e2b38e389ee6bc91de2e9b
Signed-off-by: Harout Hedeshian <harouth@codeaurora.org>
Diffstat (limited to 'net/rmnet_data/rmnet_map_command.c')
| -rw-r--r-- | net/rmnet_data/rmnet_map_command.c | 94 |
1 files changed, 91 insertions, 3 deletions
diff --git a/net/rmnet_data/rmnet_map_command.c b/net/rmnet_data/rmnet_map_command.c index 68acf2d9561a..a3a5bfc705dd 100644 --- a/net/rmnet_data/rmnet_map_command.c +++ b/net/rmnet_data/rmnet_map_command.c @@ -20,18 +20,95 @@ #include "rmnet_data_config.h" #include "rmnet_map.h" #include "rmnet_data_private.h" +#include "rmnet_data_vnd.h" + +RMNET_LOG_MODULE(RMNET_DATA_LOGMASK_MAPC); unsigned long int rmnet_map_command_stats[RMNET_MAP_COMMAND_ENUM_LENGTH]; module_param_array(rmnet_map_command_stats, ulong, 0, S_IRUGO); MODULE_PARM_DESC(rmnet_map_command_stats, "MAP command statistics"); +/** + * rmnet_map_do_flow_control() - Process MAP flow control command + * @skb: Socket buffer containing the MAP flow control message + * @config: Physical end-point configuration of ingress device + * @enable: boolean for enable/disable + * + * Process in-band MAP flow control messages. Assumes mux ID is mapped to a + * RmNet Data vitrual network device. + * + * Return: + * - RMNET_MAP_COMMAND_UNSUPPORTED on any error + * - RMNET_MAP_COMMAND_ACK on success + */ static uint8_t rmnet_map_do_flow_control(struct sk_buff *skb, struct rmnet_phys_ep_conf_s *config, int enable) { - return RMNET_MAP_COMMAND_UNSUPPORTED; + struct rmnet_map_control_command_s *cmd; + struct net_device *vnd; + struct rmnet_logical_ep_conf_s *ep; + uint8_t mux_id; + uint16_t ip_family; + uint16_t fc_seq; + uint32_t qos_id; + int r; + + if (unlikely(!skb || !config)) + BUG(); + + mux_id = RMNET_MAP_GET_MUX_ID(skb); + cmd = RMNET_MAP_GET_CMD_START(skb); + + if (mux_id >= RMNET_DATA_MAX_LOGICAL_EP) { + LOGD("%s(): Got packet on %s with bad mux id %d\n", + __func__, skb->dev->name, mux_id); + kfree_skb(skb); + return RX_HANDLER_CONSUMED; + } + + ep = &(config->muxed_ep[mux_id]); + + if (!ep->refcount) { + LOGD("%s(): Packet on %s:%d; has no logical endpoint config\n", + __func__, skb->dev->name, mux_id); + + kfree_skb(skb); + return RX_HANDLER_CONSUMED; + } + + vnd = ep->egress_dev; + + ip_family = cmd->flow_control.ip_family; + fc_seq = ntohs(cmd->flow_control.flow_control_seq_num); + qos_id = ntohl(cmd->flow_control.qos_id); + + /* Ignore the ip family and pass the sequence number for both v4 and v6 + * sequence. User space does not support creating dedicated flows for + * the 2 protocols + */ + r = rmnet_vnd_do_flow_control(vnd, qos_id, fc_seq, fc_seq, enable); + LOGD("%s(): dev:%s, qos_id:0x%08X, ip_family:%hd, fc_seq %hd, en:%d\n", + __func__, skb->dev->name, qos_id, ip_family & 3, fc_seq, enable); + + if (r) + return RMNET_MAP_COMMAND_UNSUPPORTED; + else + return RMNET_MAP_COMMAND_ACK; } +/** + * rmnet_map_send_ack() - Send N/ACK message for MAP commands + * @skb: Socket buffer containing the MAP command message + * @type: N/ACK message selector + * + * skb is modified to contain the message type selector. The message is then + * transmitted on skb->dev. Note that this function grabs global Tx lock on + * skb->dev for latency reasons. + * + * Return: + * - void + */ static void rmnet_map_send_ack(struct sk_buff *skb, unsigned char type) { @@ -53,6 +130,17 @@ static void rmnet_map_send_ack(struct sk_buff *skb, spin_unlock_irqrestore(&(skb->dev->tx_global_lock), flags); } +/** + * rmnet_map_command() - Entry point for handling MAP commands + * @skb: Socket buffer containing the MAP command message + * @config: Physical end-point configuration of ingress device + * + * Process MAP command frame and send N/ACK message as appropriate. Message cmd + * name is decoded here and appropriate handler is called. + * + * Return: + * - RX_HANDLER_CONSUMED. Command frames are always consumed. + */ rx_handler_result_t rmnet_map_command(struct sk_buff *skb, struct rmnet_phys_ep_conf_s *config) { @@ -60,7 +148,7 @@ rx_handler_result_t rmnet_map_command(struct sk_buff *skb, unsigned char command_name; unsigned char rc = 0; - if (!skb) + if (unlikely(!skb)) BUG(); cmd = RMNET_MAP_GET_CMD_START(skb); @@ -85,5 +173,5 @@ rx_handler_result_t rmnet_map_command(struct sk_buff *skb, break; } rmnet_map_send_ack(skb, rc); - return 0; /* TODO: handler_consumed */ + return RX_HANDLER_CONSUMED; } |
