Add notify message handling for LAG interfaces.

Change-Id: I8900d00207768e349c9d7e7936aa288278154bd8
Signed-off-by: Tushar Mathur <tushar@codeaurora.org>
diff --git a/nss_connmgr_ipv4.c b/nss_connmgr_ipv4.c
index 95985bc..20cde91 100755
--- a/nss_connmgr_ipv4.c
+++ b/nss_connmgr_ipv4.c
@@ -420,6 +420,8 @@
  */
 extern nss_tx_status_t nss_send_lag_state(struct nss_ctx_instance *ctx, struct net_device *netdev);
 
+extern nss_lag_event_callback_t nss_connmgr_lag_event_cb;
+
 /*
  * Network flow
  *
@@ -3584,6 +3586,10 @@
 		debugfs_remove(dent);
 	}
 
+	/* Register Link Aggregation interfaces with NSS driver */
+	nss_register_lag_if(NSS_LAG0_INTERFACE_NUM, NULL, nss_connmgr_lag_event_cb, NULL);
+	nss_register_lag_if(NSS_LAG1_INTERFACE_NUM, NULL, nss_connmgr_lag_event_cb, NULL);
+
 	/*
 	 * Register Link Aggregation callbacks
 	 */
@@ -3603,6 +3609,10 @@
 {
 	bond_unregister_cb();
 
+	/* Unregister Link Aggregation interfaces with NSS driver */
+	nss_unregister_lag_if(NSS_LAG0_INTERFACE_NUM);
+	nss_unregister_lag_if(NSS_LAG1_INTERFACE_NUM);
+
 	/*
 	 * Remove debugfs tree
 	 */
diff --git a/nss_connmgr_lag.c b/nss_connmgr_lag.c
index 0b435f6..6cea1fd 100755
--- a/nss_connmgr_lag.c
+++ b/nss_connmgr_lag.c
@@ -23,6 +23,8 @@
 
 #include "nss_api_if.h"
 
+#define nss_lag_info(fmt, args...) printk(KERN_INFO "nss LAG :"fmt, ##args)
+
 /*
  * nss_send_lag_state()
  *	Send the currnet LAG state of a physical interface.
@@ -71,5 +73,18 @@
 }
 
 
-
-
+/**
+ * @brief Event Callback to receive events from NSS
+ * @param[in] pointer to net device context
+ * @param[in] pointer to buffer
+ * @return Returns void
+ */
+void nss_connmgr_lag_event_cb(void *if_ctx, struct nss_lag_msg *msg)
+{
+	switch (msg->cm.type)
+	{
+		default:
+			nss_lag_info("%s: Unknown LAG event from NSS",__FUNCTION__);
+			break;
+	}
+}
diff --git a/nss_core.h b/nss_core.h
index 04a84fe..07c604d 100755
--- a/nss_core.h
+++ b/nss_core.h
@@ -495,6 +495,7 @@
 					/* Registrants for interface shaper bounce operations */
 	struct nss_shaper_bounce_registrant bounce_bridge_registrants[NSS_MAX_NET_INTERFACES];
 					/* Registrants for bridge shaper bounce operations */
+	nss_lag_event_callback_t lag_event_callback;
 
 	/*
 	 * Interface contexts (network device)
diff --git a/nss_init.c b/nss_init.c
index 17c8513..3132e3e 100755
--- a/nss_init.c
+++ b/nss_init.c
@@ -340,6 +340,7 @@
 		nss_eth_rx_register_handler();
 		nss_n2h_register_handler();
 		nss_virt_if_register_handler();
+		nss_lag_register_handler();
 		for (i = 0; i < NSS_MAX_VIRTUAL_INTERFACES; i++) {
 			nss_top->virt_if_handler_id[i] = nss_dev->id;
 		}
diff --git a/nss_lag.c b/nss_lag.c
index a39bd36..cdb0d96 100755
--- a/nss_lag.c
+++ b/nss_lag.c
@@ -66,3 +66,98 @@
 	return NSS_TX_SUCCESS;
 }
 EXPORT_SYMBOL(nss_lag_tx);
+
+/**
+ * nss_register_lag_if()
+ */
+void nss_register_lag_if(uint32_t if_num,
+			 nss_lag_callback_t lag_cb,
+			 nss_lag_event_callback_t lag_ev_cb,
+			 struct net_device *netdev)
+{
+	nss_assert((if_num != NSS_LAG0_INTERFACE_NUM) && (if_num != NSS_LAG1_INTERFACE_NUM));
+
+	nss_top_main.if_ctx[if_num] = netdev;
+	nss_top_main.if_rx_callback[if_num] = lag_cb;
+	nss_top_main.lag_event_callback = lag_ev_cb;
+}
+EXPORT_SYMBOL(nss_register_lag_if);
+
+
+/**
+ * nss_unregister_lag_if()
+ */
+void nss_unregister_lag_if(uint32_t if_num)
+{
+	nss_assert((if_num != NSS_LAG0_INTERFACE_NUM) && (if_num != NSS_LAG1_INTERFACE_NUM));
+
+	nss_top_main.if_rx_callback[if_num] = NULL;
+	nss_top_main.if_ctx[if_num] = NULL;
+	nss_top_main.lag_event_callback = NULL;
+}
+EXPORT_SYMBOL(nss_unregister_lag_if);
+
+
+/**
+ * nss_lag_handler()
+ */
+void nss_lag_handler(struct nss_ctx_instance *nss_ctx,
+		     struct nss_cmn_msg *ncm,
+		     void *app_data)
+{
+	struct nss_lag_msg *lm = (struct nss_lag_msg *)ncm;
+	void *ctx = NULL;
+	nss_lag_event_callback_t cb;
+
+	BUG_ON(ncm->interface != NSS_LAG0_INTERFACE_NUM
+	       && ncm->interface != NSS_LAG1_INTERFACE_NUM);
+
+	if (ncm->type >= NSS_TX_METADATA_LAG_MAX) {
+		nss_warning("%p: received invalid message %d for LAG interface", nss_ctx, ncm->type);
+		return;
+	}
+
+	if (ncm->len > sizeof(struct nss_lag_msg)) {
+		nss_warning("%p: invalid length for LAG message: %d", nss_ctx, ncm->len);
+		return;
+	}
+
+	/**
+	 * Update the callback and app_data for NOTIFY messages.
+	 * LAG sends all notify messages to the same callback.
+	 */
+	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+		ncm->cb = (uint32_t)nss_ctx->nss_top->lag_event_callback;
+	}
+
+	/**
+	 * Log failures
+	 */
+	nss_core_log_msg_failures(nss_ctx, ncm);
+
+	/**
+	 * Do we have a call back
+	 */
+	if (!ncm->cb) {
+		return;
+	}
+
+	/**
+	 * callback
+	 */
+	cb = (nss_lag_event_callback_t)ncm->cb;
+	ctx = nss_ctx->nss_top->if_ctx[ncm->interface];
+
+	cb(ctx, lm);
+}
+
+
+/**
+ * nss_lag_register_handler()
+ */
+void nss_lag_register_handler(void)
+{
+	nss_core_register_handler(NSS_LAG0_INTERFACE_NUM, nss_lag_handler, NULL);
+	nss_core_register_handler(NSS_LAG1_INTERFACE_NUM, nss_lag_handler, NULL);
+}
+
diff --git a/nss_lag.h b/nss_lag.h
index d3dc166..8e3d235 100755
--- a/nss_lag.h
+++ b/nss_lag.h
@@ -24,6 +24,7 @@
  */
 enum nss_lag_metadata_types {
 	NSS_TX_METADATA_LAG_STATE_CHANGE = 0,
+	NSS_TX_METADATA_LAG_MAX,
 };
 
 /*
@@ -63,3 +64,19 @@
 
 extern nss_tx_status_t nss_lag_tx(struct nss_ctx_instance *nss_ctx, struct nss_lag_msg *msg);
 
+/**
+ * Callback to receive LAG data
+ */
+typedef void (*nss_lag_callback_t)(void *app_data, void *os_buf);
+
+/**
+ * Callback to receive LAG events
+ */
+typedef void (*nss_lag_event_callback_t)(void *app_data, struct nss_lag_msg *msg);
+
+extern void nss_register_lag_if(uint32_t if_num,
+				nss_lag_callback_t lag_cb,
+				nss_lag_event_callback_t lag_ev_cb,
+				struct net_device *netdev);
+
+extern void nss_unregister_lag_if(uint32_t if_num);
diff --git a/nss_tx_rx_common.h b/nss_tx_rx_common.h
index 2ed8514..31e78b8 100755
--- a/nss_tx_rx_common.h
+++ b/nss_tx_rx_common.h
@@ -73,5 +73,6 @@
 extern void nss_pppoe_register_handler(void);
 extern void nss_core_freq_register_handler(void);
 extern void nss_eth_rx_register_handler(void);
+extern void nss_lag_register_handler(void);
 
 #endif /* __NSS_TX_RX_COMMON_H */