summaryrefslogtreecommitdiff
path: root/net/rmnet_data/rmnet_map_command.c
diff options
context:
space:
mode:
authorHarout Hedeshian <harouth@codeaurora.org>2013-10-24 09:28:22 -0600
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:04:58 -0700
commit3a9fa2aa8025735dcbf413d02ac694fd636f21f5 (patch)
tree828d05b792c5566ca5db15821cba66d3344f3c4e /net/rmnet_data/rmnet_map_command.c
parent162318ea3eec2d52f7f46752fb3be10541953289 (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.c94
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;
}