[qca-nss-ecm]: Support for bond-L2DA mode
Added one callback to defuct all the connection
of a bond slave.
Change-Id: Ie04f3d4949951dbf0ca032b720f80e219c7fcb26
Signed-off-by: Suman Ghosh <sumang@codeaurora.org>
diff --git a/ecm_interface.c b/ecm_interface.c
index c482af6..e3d5247 100644
--- a/ecm_interface.c
+++ b/ecm_interface.c
@@ -5015,6 +5015,102 @@
}
/*
+ * ecm_interface_defunct_connections()
+ * Cause defunct of all connections that are using the specified interface.
+ */
+static void ecm_interface_defunct_connections(struct ecm_db_iface_instance *ii)
+{
+#ifndef ECM_DB_XREF_ENABLE
+ ecm_db_connection_defunct_all();
+#else
+ struct ecm_db_connection_instance *ci_from;
+ struct ecm_db_connection_instance *ci_to;
+ struct ecm_db_connection_instance *ci_from_nat;
+ struct ecm_db_connection_instance *ci_to_nat;
+ struct ecm_db_connection_instance *ci_mcast __attribute__ ((unused));
+
+ DEBUG_TRACE("defunct connections using interface: %p\n", ii);
+
+ ci_from = ecm_db_iface_connections_from_get_and_ref_first(ii);
+ ci_to = ecm_db_iface_connections_to_get_and_ref_first(ii);
+ ci_from_nat = ecm_db_iface_connections_nat_from_get_and_ref_first(ii);
+ ci_to_nat = ecm_db_iface_connections_nat_to_get_and_ref_first(ii);
+
+ /*
+ * Defunct all connections associated with this interface
+ */
+ DEBUG_TRACE("%p: Defunct 'from' connections\n", ii);
+ while (ci_from) {
+ struct ecm_db_connection_instance *cin;
+ cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from);
+
+ DEBUG_TRACE("%p: Defunct: %p", ii, ci_from);
+ ecm_db_connection_make_defunct(ci_from);
+ ecm_db_connection_deref(ci_from);
+ ci_from = cin;
+ }
+
+ DEBUG_TRACE("%p: Defunct 'to' connections\n", ii);
+ while (ci_to) {
+ struct ecm_db_connection_instance *cin;
+ cin = ecm_db_connection_iface_from_get_and_ref_next(ci_to);
+
+ DEBUG_TRACE("%p: Defunct: %p", ii, ci_to);
+ ecm_db_connection_make_defunct(ci_to);
+ ecm_db_connection_deref(ci_to);
+ ci_to = cin;
+ }
+
+ DEBUG_TRACE("%p: Defunct 'from_nat' connections\n", ii);
+ while (ci_from_nat) {
+ struct ecm_db_connection_instance *cin;
+ cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from_nat);
+
+ DEBUG_TRACE("%p: Defunct: %p", ii, ci_from_nat);
+ ecm_db_connection_make_defunct(ci_from_nat);
+ ecm_db_connection_deref(ci_from_nat);
+ ci_from_nat = cin;
+ }
+
+ DEBUG_TRACE("%p: Defunct 'to_nat' connections\n", ii);
+ while (ci_to_nat) {
+ struct ecm_db_connection_instance *cin;
+ cin = ecm_db_connection_iface_from_get_and_ref_next(ci_to_nat);
+
+ DEBUG_TRACE("%p: Defunct: %p", ii, ci_to_nat);
+ ecm_db_connection_make_defunct(ci_to_nat);
+ ecm_db_connection_deref(ci_to_nat);
+ ci_to_nat = cin;
+ }
+#endif
+ DEBUG_TRACE("%p: Defunct COMPLETE\n", ii);
+}
+
+/*
+ * ecm_interface_dev_defunct_connections()
+ * Cause defunct of all connections that are using the specified interface.
+ */
+void ecm_interface_dev_defunct_connections(struct net_device *dev)
+{
+ struct ecm_db_iface_instance *ii;
+
+ DEBUG_INFO("defunct connections for: %p (%s)\n", dev, dev->name);
+
+ /*
+ * If the interface is known to us then we will get it returned by this
+ * function and process it accordingly.
+ */
+ ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
+ if (!ii) {
+ DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
+ return;
+ }
+ ecm_interface_defunct_connections(ii);
+ DEBUG_TRACE("%p: defunct for %p: COMPLETE\n", dev, ii);
+ ecm_db_iface_deref(ii);
+}
+
+/*
* ecm_interface_mtu_change()
* MTU of interface has changed
*/
diff --git a/ecm_interface.h b/ecm_interface.h
index 866dc68..be9b94a 100644
--- a/ecm_interface.h
+++ b/ecm_interface.h
@@ -104,3 +104,4 @@
void ecm_interface_dev_regenerate_connections(struct net_device *dev);
struct net_device *ecm_interface_dev_find_by_local_addr(ip_addr_t addr);
bool ecm_interface_find_gateway(ip_addr_t addr, ip_addr_t gw_addr);
+void ecm_interface_dev_defunct_connections(struct net_device *dev);
diff --git a/frontends/nss/ecm_nss_bond_notifier.c b/frontends/nss/ecm_nss_bond_notifier.c
index fa61df5..b2eff6d 100644
--- a/frontends/nss/ecm_nss_bond_notifier.c
+++ b/frontends/nss/ecm_nss_bond_notifier.c
@@ -284,6 +284,74 @@
}
/*
+ * ecm_nss_bond_notifier_bond_delete_by_slave()
+ * Callback when defunct a LAG slave
+ */
+static void ecm_nss_bond_notifier_bond_delete_by_slave(struct net_device *slave_dev)
+{
+ struct net_device *master;
+
+ /*
+ * If operations have stopped then do not process event
+ */
+ spin_lock_bh(&ecm_nss_bond_notifier_lock);
+ if (unlikely(ecm_nss_bond_notifier_stopped)) {
+ spin_unlock_bh(&ecm_nss_bond_notifier_lock);
+ DEBUG_WARN("Ignoring bond defunct event - stopped\n");
+ return;
+ }
+ spin_unlock_bh(&ecm_nss_bond_notifier_lock);
+
+ /*
+ * A net device that is a LAG slave has to
+ * defunct all the connection.
+ * Due to the heiarchical nature of network topologies, this can
+ * change the packet transmit path for any connection that is using
+ * a device that it sitting "higher" in the heirarchy.
+ */
+ master = ecm_interface_get_and_hold_dev_master(slave_dev);
+ if (!master) {
+ DEBUG_WARN("Failed to find 'master' for the slave:%s\n", slave_dev->name);
+ return;
+ }
+
+ ecm_interface_dev_defunct_connections(master);
+ dev_put(master);
+}
+
+/*
+ * ecm_nss_bond_notifier_bond_delete_by_mac()
+ * This is a call back to delete all the rules with the mac address
+ */
+static void ecm_nss_bond_notifier_bond_delete_by_mac(uint8_t *mac)
+{
+ struct ecm_db_node_instance *ni;
+
+ if (unlikely(!mac)) {
+ DEBUG_WARN("mac address passed to ecm_nss_bond_notifier_bond_delete_by_mac is null \n");
+ return;
+ }
+
+ /*
+ * find node instance corresponding to mac address
+ */
+ ni = ecm_db_node_find_and_ref(mac);
+ if (unlikely(!ni)) {
+ DEBUG_WARN("node address is null\n");
+ return;
+ }
+
+ DEBUG_INFO("FDB updated for node %pM\n", mac);
+ ecm_db_traverse_node_from_connection_list_and_decelerate(ni);
+ ecm_db_traverse_node_to_connection_list_and_decelerate(ni);
+ ecm_db_traverse_node_from_nat_connection_list_and_decelerate(ni);
+ ecm_db_traverse_node_to_nat_connection_list_and_decelerate(ni);
+
+ ecm_db_node_deref(ni);
+ return;
+}
+
+/*
* ecm_nss_bond_notifier_lag_event_cb()
* Handle LAG event from the NSS driver
*/
@@ -352,6 +420,8 @@
ecm_nss_bond_notifier_bond_cb.bond_cb_link_down = ecm_nss_bond_notifier_bond_link_down;
ecm_nss_bond_notifier_bond_cb.bond_cb_release = ecm_nss_bond_notifier_bond_release;
ecm_nss_bond_notifier_bond_cb.bond_cb_enslave = ecm_nss_bond_notifier_bond_enslave;
+ ecm_nss_bond_notifier_bond_cb.bond_cb_delete_by_slave = ecm_nss_bond_notifier_bond_delete_by_slave;
+ ecm_nss_bond_notifier_bond_cb.bond_cb_delete_by_mac = ecm_nss_bond_notifier_bond_delete_by_mac;
bond_register_cb(&ecm_nss_bond_notifier_bond_cb);
return 0;