From 29c93682aa24f85ba10c88b0ce88ce76352c6b03 Mon Sep 17 00:00:00 2001 From: lean Date: Wed, 16 Feb 2022 14:41:12 +0800 Subject: [PATCH] qca-nss-ecm: add support for macvlan interface acceleration --- package/qca/nss/qca-nss-ecm/Makefile | 4 + ...204-add-macvlan-acceleration-support.patch | 628 ++++++++++++++++++ 2 files changed, 632 insertions(+) create mode 100644 package/qca/nss/qca-nss-ecm/patches/204-add-macvlan-acceleration-support.patch diff --git a/package/qca/nss/qca-nss-ecm/Makefile b/package/qca/nss/qca-nss-ecm/Makefile index 06ce3ffc4..0ed611df0 100644 --- a/package/qca/nss/qca-nss-ecm/Makefile +++ b/package/qca/nss/qca-nss-ecm/Makefile @@ -218,6 +218,10 @@ ECM_MAKE_OPTS+=ECM_INTERFACE_OVS_BRIDGE_ENABLE=y \ EXTRA_CFLAGS+= -I$(STAGING_DIR)/usr/include/qca-ovsmgr endif +ifneq ($(CONFIG_PACKAGE_kmod-macvlan),) +ECM_MAKE_OPTS+=ECM_INTERFACE_MACVLAN_ENABLE=y +endif + # Keeping default as ipq806x for branches that does not have subtarget framework ifeq ($(CONFIG_TARGET_ipq),y) subtarget:=$(SUBTARGET) diff --git a/package/qca/nss/qca-nss-ecm/patches/204-add-macvlan-acceleration-support.patch b/package/qca/nss/qca-nss-ecm/patches/204-add-macvlan-acceleration-support.patch new file mode 100644 index 000000000..1c0879dd6 --- /dev/null +++ b/package/qca/nss/qca-nss-ecm/patches/204-add-macvlan-acceleration-support.patch @@ -0,0 +1,628 @@ +--- a/Makefile ++++ b/Makefile +@@ -196,6 +196,11 @@ ECM_INTERFACE_VLAN_ENABLE=y + ccflags-$(ECM_INTERFACE_VLAN_ENABLE) += -DECM_INTERFACE_VLAN_ENABLE + + # ############################################################################# ++# Define ECM_INTERFACE_MACVLAN_ENABLE=y in order to enable support for MACVLAN ++# ############################################################################# ++ccflags-$(ECM_INTERFACE_MACVLAN_ENABLE) += -DECM_INTERFACE_MACVLAN_ENABLE ++ ++# ############################################################################# + # Define ECM_INTERFACE_IPSEC_ENABLE=y in order to enable support for IPSEC + # ############################################################################# + ccflags-$(ECM_INTERFACE_IPSEC_ENABLE) += -DECM_INTERFACE_IPSEC_ENABLE +--- a/ecm_interface.c ++++ b/ecm_interface.c +@@ -94,6 +94,9 @@ + #ifdef ECM_INTERFACE_OVS_BRIDGE_ENABLE + #include + #endif ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++#include ++#endif + + /* + * Debug output levels +@@ -1498,6 +1501,58 @@ static struct ecm_db_iface_instance *ecm + } + #endif + ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++/* ++ * ecm_interface_macvlan_interface_establish() ++ * Returns a reference to a iface of the MACVLAN type, possibly creating one if necessary. ++ * Returns NULL on failure or a reference to interface. ++ */ ++static struct ecm_db_iface_instance *ecm_interface_macvlan_interface_establish(struct ecm_db_interface_info_macvlan *type_info, ++ char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu) ++{ ++ struct ecm_db_iface_instance *nii; ++ struct ecm_db_iface_instance *ii; ++ ++ DEBUG_INFO("Establish MACVLAN iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n", ++ dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num); ++ ++ /* ++ * Locate the iface ++ */ ++ ii = ecm_db_iface_find_and_ref_macvlan(type_info->address); ++ if (ii) { ++ DEBUG_TRACE("%px: iface established\n", ii); ++ return ii; ++ } ++ ++ /* ++ * No iface - create one ++ */ ++ nii = ecm_db_iface_alloc(); ++ if (!nii) { ++ DEBUG_WARN("Failed to establish iface\n"); ++ return NULL; ++ } ++ ++ /* ++ * Add iface into the database, atomically to avoid races creating the same thing ++ */ ++ spin_lock_bh(&ecm_interface_lock); ++ ii = ecm_db_iface_find_and_ref_macvlan(type_info->address); ++ if (ii) { ++ spin_unlock_bh(&ecm_interface_lock); ++ ecm_db_iface_deref(nii); ++ return ii; ++ } ++ ecm_db_iface_add_macvlan(nii, type_info->address, dev_name, ++ mtu, dev_interface_num, ae_interface_num, NULL, nii); ++ spin_unlock_bh(&ecm_interface_lock); ++ ++ DEBUG_TRACE("%px: MACVLAN iface established\n", nii); ++ return nii; ++} ++#endif ++ + #ifdef ECM_INTERFACE_OVS_BRIDGE_ENABLE + /* + * ecm_interface_multicast_ovs_to_interface_get_and_ref() +@@ -2634,6 +2689,28 @@ static struct net_device *ecm_interface_ + } + #endif + ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++/* ++ * ecm_interface_macvlan_mode_is_valid() ++ * Check if the macvlan interface allowed for acceleration. ++ */ ++static bool ecm_interface_macvlan_mode_is_valid(struct net_device *dev) ++{ ++ enum macvlan_mode mode = macvlan_get_mode(dev); ++ ++ /* ++ * Allow acceleration for only "Private" mode. ++ */ ++ if (mode == MACVLAN_MODE_PRIVATE) { ++ return true; ++ } ++ ++ DEBUG_WARN("%px: MACVLAN dev: %s, MACVLAN mode: %d is not supported for acceleration\n", dev, ++ dev->name, mode); ++ return false; ++} ++#endif ++ + /* + * ecm_interface_establish_and_ref() + * Establish an interface instance for the given interface detail. +@@ -2653,6 +2730,9 @@ struct ecm_db_iface_instance *ecm_interf + #ifdef ECM_INTERFACE_VLAN_ENABLE + struct ecm_db_interface_info_vlan vlan; /* type == ECM_DB_IFACE_TYPE_VLAN */ + #endif ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ struct ecm_db_interface_info_macvlan macvlan; /* type == ECM_DB_IFACE_TYPE_MACVLAN */ ++#endif + #ifdef ECM_INTERFACE_BOND_ENABLE + struct ecm_db_interface_info_lag lag; /* type == ECM_DB_IFACE_TYPE_LAG */ + #endif +@@ -2780,6 +2860,28 @@ struct ecm_db_iface_instance *ecm_interf + } + #endif + ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ /* ++ * MACVLAN? ++ */ ++ if (netif_is_macvlan(dev)) { ++ if (ecm_interface_macvlan_mode_is_valid(dev)) { ++ ether_addr_copy(type_info.macvlan.address, dev->dev_addr); ++ DEBUG_TRACE("%px: Net device: %px is MACVLAN, mac: %pM\n", ++ feci, dev, type_info.macvlan.address); ++ ++ /* ++ * Establish this type of interface ++ */ ++ ii = ecm_interface_macvlan_interface_establish(&type_info.macvlan, dev_name, dev_interface_num, ae_interface_num, dev_mtu); ++ goto identifier_update; ++ } ++ ++ DEBUG_WARN("%px: Net device %px MACVLAN mode is not supported.\n", feci, dev); ++ return NULL; ++ } ++#endif ++ + #ifdef ECM_INTERFACE_VXLAN_ENABLE + /* + * VxLAN? +@@ -3606,6 +3708,21 @@ static uint32_t ecm_interface_multicast_ + break; + } + ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ /* ++ * MAC-VLAN? ++ */ ++ if (netif_is_macvlan(dest_dev)) { ++ if (ecm_interface_macvlan_mode_is_valid(dest_dev)) { ++ next_dev = macvlan_dev_real_dev(dest_dev); ++ dev_hold(next_dev); ++ DEBUG_TRACE("%px: Net device: %px is MAC-VLAN, slave dev: %px (%s)\n", ++ feci, dest_dev, next_dev, next_dev->name); ++ break; ++ } ++ } ++#endif ++ + #ifdef ECM_INTERFACE_BOND_ENABLE + /* + * LAG? +@@ -4746,6 +4863,35 @@ int32_t ecm_interface_heirarchy_construc + } + #endif + ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ /* ++ * MAC-VLAN? ++ */ ++ if (netif_is_macvlan(dest_dev)) { ++ if (ecm_interface_macvlan_mode_is_valid(dest_dev)) { ++ next_dev = macvlan_dev_real_dev(dest_dev); ++ dev_hold(next_dev); ++ DEBUG_TRACE("%px: Net device: %px is MAC-VLAN, slave dev: %px (%s)\n", ++ feci, dest_dev, next_dev, next_dev->name); ++ ++ /* ++ * We need to take the master_dev's MAC address during ++ * NSS rule push. During VLAN/MACVLAN the master_dev for the ++ * physical interface will be set to NULL but still we need the ++ * VLAN/MACVLAN dev's MAC address while pushing the rule. We identify ++ * the same using top_dev variable. ++ */ ++ if (current_interface_index == (ECM_DB_IFACE_HEIRARCHY_MAX - 1)) { ++ top_dev = dest_dev; ++ } ++ break; ++ } ++ ++ DEBUG_WARN("%px: Net device %px MACVLAN mode is not supported.\n", feci, dest_dev); ++ goto done; ++ } ++#endif ++ + /* + * BRIDGE? + */ +@@ -5595,6 +5741,21 @@ int32_t ecm_interface_multicast_from_hei + } + #endif + ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ /* ++ * MAC-VLAN? ++ */ ++ if (netif_is_macvlan(dest_dev)) { ++ if (ecm_interface_macvlan_mode_is_valid(dest_dev)) { ++ next_dev = macvlan_dev_real_dev(dest_dev); ++ dev_hold(next_dev); ++ DEBUG_TRACE("%px: Net device: %px is MAC-VLAN, slave dev: %px (%s)\n", ++ feci, dest_dev, next_dev, next_dev->name); ++ break; ++ } ++ } ++#endif ++ + /* + * BRIDGE? + */ +@@ -6041,10 +6202,13 @@ static void ecm_interface_ovpn_stats_upd + * Given an interface list, walk the interfaces and update the stats for certain types. + */ + static void ecm_interface_list_stats_update(int iface_list_first, struct ecm_db_iface_instance *iface_list[], +- uint8_t *mac_addr, bool is_mcast_flow, uint32_t tx_packets, uint32_t tx_bytes, uint32_t rx_packets, ++ uint8_t *mac_addr, bool is_mcast_to_if, uint32_t tx_packets, uint32_t tx_bytes, uint32_t rx_packets, + uint32_t rx_bytes, bool is_ported, struct ecm_db_connection_instance *ci) + { + int list_index; ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ bool update_mcast_rx_stats = false; ++#endif + + for (list_index = iface_list_first; (list_index < ECM_DB_IFACE_HEIRARCHY_MAX); list_index++) { + struct ecm_db_iface_instance *ii; +@@ -6067,7 +6231,7 @@ static void ecm_interface_list_stats_upd + } + DEBUG_TRACE("found dev: %p (%s)\n", dev, dev->name); + +- if (likely(!is_mcast_flow)) { ++ if (likely(!is_mcast_to_if)) { + /* + * Refresh the bridge forward table entry if the port is a bridge port. + * Refresh if the ci is a 3-tuple PPPoE bridge flow. +@@ -6126,6 +6290,24 @@ static void ecm_interface_list_stats_upd + } + break; + #endif ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ case ECM_DB_IFACE_TYPE_MACVLAN: ++ DEBUG_INFO("MACVLAN\n"); ++ stats.rx_packets = rx_packets; ++ stats.rx_bytes = rx_bytes; ++ stats.tx_packets = tx_packets; ++ stats.tx_bytes = tx_bytes; ++#ifdef ECM_MULTICAST_ENABLE ++ /* ++ * Update multicast rx statistics only for ++ * 'from' interface. ++ */ ++ update_mcast_rx_stats = (!is_mcast_to_if && ++ ecm_db_multicast_connection_to_interfaces_set_check(ci)); ++#endif ++ macvlan_offload_stats_update(dev, &stats, update_mcast_rx_stats); ++ break; ++#endif + default: + /* + * TODO: Extend it accordingly +@@ -6226,7 +6408,7 @@ void ecm_interface_multicast_stats_updat + DEBUG_INFO("%p: Update from interface stats\n", ci); + from_ifaces_first = ecm_db_connection_interfaces_get_and_ref(ci, from_ifaces, ECM_DB_OBJ_DIR_FROM); + ecm_db_connection_node_address_get(ci, ECM_DB_OBJ_DIR_FROM, mac_addr); +- ecm_interface_list_stats_update(from_ifaces_first, from_ifaces, mac_addr, false, from_tx_packets, from_tx_bytes, from_rx_packets, from_rx_bytes, is_ported, ci); ++ ecm_interface_list_stats_update(from_ifaces_first, from_ifaces, mac_addr, false, 0, 0, from_rx_packets, from_rx_bytes, is_ported, ci); + ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first); + + /* +@@ -6250,7 +6432,7 @@ void ecm_interface_multicast_stats_updat + if (to_ifaces_first[if_index] < ECM_DB_IFACE_HEIRARCHY_MAX) { + ii_temp = ecm_db_multicast_if_heirarchy_get(to_ifaces, if_index); + ecm_db_multicast_copy_if_heirarchy(to_list_single, ii_temp); +- ecm_interface_list_stats_update(to_ifaces_first[if_index], to_list_single, mac_addr, true, to_tx_packets, to_tx_bytes, to_rx_packets, to_rx_bytes, is_ported, ci); ++ ecm_interface_list_stats_update(to_ifaces_first[if_index], to_list_single, mac_addr, true, from_tx_packets, from_tx_bytes, 0, 0, is_ported, ci); + } + } + +--- a/ecm_db/ecm_db_types.h ++++ b/ecm_db/ecm_db_types.h +@@ -275,6 +275,7 @@ enum ecm_db_iface_types { + ECM_DB_IFACE_TYPE_OVPN, /* Interface is a OVPN interface */ + ECM_DB_IFACE_TYPE_VXLAN, /* Interface is a VxLAN interface */ + ECM_DB_IFACE_TYPE_OVS_BRIDGE, /* Interface is a OpenvSwitch bridge interface */ ++ ECM_DB_IFACE_TYPE_MACVLAN, /* Interface is a MACVLAN interface */ + ECM_DB_IFACE_TYPE_COUNT, /* Number of interface types */ + }; + typedef enum ecm_db_iface_types ecm_db_iface_type_t; +@@ -301,6 +302,12 @@ struct ecm_db_interface_info_vlan { /* + }; + #endif + ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++struct ecm_db_interface_info_macvlan { /* type == ECM_DB_IFACE_TYPE_MACVLAN */ ++ uint8_t address[ETH_ALEN]; /* MAC Address of this Interface */ ++}; ++#endif ++ + #ifdef ECM_INTERFACE_BOND_ENABLE + struct ecm_db_interface_info_lag { /* type == ECM_DB_IFACE_TYPE_LAG */ + uint8_t address[ETH_ALEN]; /* MAC Address of this Interface */ +--- a/ecm_db/ecm_db_iface.h ++++ b/ecm_db/ecm_db_iface.h +@@ -94,6 +94,9 @@ struct ecm_db_iface_instance { + #ifdef ECM_INTERFACE_VLAN_ENABLE + struct ecm_db_interface_info_vlan vlan; /* type == ECM_DB_IFACE_TYPE_VLAN */ + #endif ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ struct ecm_db_interface_info_macvlan macvlan; /* type == ECM_DB_IFACE_TYPE_MACVLAN */ ++#endif + #ifdef ECM_INTERFACE_BOND_ENABLE + struct ecm_db_interface_info_lag lag; /* type == ECM_DB_IFACE_TYPE_LAG */ + #endif +@@ -215,6 +218,10 @@ void ecm_db_iface_add_vlan(struct ecm_db + #endif + + struct ecm_db_iface_instance *ecm_db_iface_find_and_ref_bridge(uint8_t *address); ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++struct ecm_db_iface_instance *ecm_db_iface_find_and_ref_macvlan(uint8_t *address); ++void ecm_db_iface_macvlan_address_get(struct ecm_db_iface_instance *ii, uint8_t *address); ++#endif + #ifdef ECM_INTERFACE_OVS_BRIDGE_ENABLE + struct ecm_db_iface_instance *ecm_db_iface_find_and_ref_ovs_bridge(uint8_t *address); + #endif +@@ -338,6 +345,11 @@ void ecm_db_iface_add_bridge(struct ecm_ + uint8_t *address, char *name, int32_t mtu, int32_t interface_identifier, + int32_t ae_interface_identifier, ecm_db_iface_final_callback_t final, void *arg); + ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++void ecm_db_iface_add_macvlan(struct ecm_db_iface_instance *ii, ++ uint8_t *address, char *name, int32_t mtu, int32_t interface_identifier, ++ int32_t ae_interface_identifier, ecm_db_iface_final_callback_t final, void *arg); ++#endif + #ifdef ECM_INTERFACE_OVS_BRIDGE_ENABLE + void ecm_db_iface_add_ovs_bridge(struct ecm_db_iface_instance *ii, + uint8_t *address, char *name, int32_t mtu, int32_t interface_identifier, +--- a/ecm_db/ecm_db_iface.c ++++ b/ecm_db/ecm_db_iface.c +@@ -114,7 +114,8 @@ static char *ecm_db_interface_type_names + "RAWIP", + "OVPN", + "VxLAN", +- "OVS_BRIDGE" ++ "OVS_BRIDGE", ++ "MACVLAN" + }; + + /* +@@ -381,6 +382,39 @@ static int ecm_db_iface_bridge_state_get + return ecm_state_prefix_remove(sfi); + } + ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++/* ++ * ecm_db_iface_macvlan_state_get() ++ * Return interface type specific state ++ */ ++static int ecm_db_iface_macvlan_state_get(struct ecm_db_iface_instance *ii, struct ecm_state_file_instance *sfi) ++{ ++ int result; ++ uint8_t address[ETH_ALEN]; ++ ++ DEBUG_CHECK_MAGIC(ii, ECM_DB_IFACE_INSTANCE_MAGIC, "%px: magic failed\n", ii); ++ spin_lock_bh(&ecm_db_lock); ++ memcpy(address, ii->type_info.macvlan.address, ETH_ALEN); ++ spin_unlock_bh(&ecm_db_lock); ++ ++ if ((result = ecm_state_prefix_add(sfi, "macvlan"))) { ++ return result; ++ } ++ ++ if ((result = ecm_db_iface_state_get_base(ii, sfi))) { ++ goto done; ++ } ++ ++ if ((result = ecm_state_write(sfi, "address", "%pM", address))) { ++ goto done; ++ } ++ ++done: ++ ecm_state_prefix_remove(sfi); ++ return result; ++} ++#endif ++ + #ifdef ECM_INTERFACE_OVS_BRIDGE_ENABLE + /* + * ecm_db_iface_ovs_bridge_state_get() +@@ -475,7 +509,7 @@ static int ecm_db_iface_pppoe_state_get( + return result; + } + +- if ((result = ecm_state_write(sfi, "remote_max", "%pM", remote_mac))) { ++ if ((result = ecm_state_write(sfi, "remote_mac", "%pM", remote_mac))) { + return result; + } + if ((result = ecm_state_write(sfi, "session_id", "%u", pppoe_session_id))) { +@@ -1645,6 +1679,58 @@ struct ecm_db_iface_instance *ecm_db_ifa + EXPORT_SYMBOL(ecm_db_iface_find_and_ref_vlan); + #endif + ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++/* ++ * ecm_db_iface_find_and_ref_macvlan() ++ * Lookup and return a iface reference if any ++ */ ++struct ecm_db_iface_instance *ecm_db_iface_find_and_ref_macvlan(uint8_t *address) ++{ ++ ecm_db_iface_hash_t hash_index; ++ struct ecm_db_iface_instance *ii; ++ ++ DEBUG_TRACE("Lookup macvlan iface with addr %pM\n", address); ++ ++ /* ++ * Compute the hash chain index and prepare to walk the chain ++ */ ++ hash_index = ecm_db_iface_generate_hash_index_ethernet(address); ++ ++ /* ++ * Iterate the chain looking for a host with matching details ++ */ ++ spin_lock_bh(&ecm_db_lock); ++ ii = ecm_db_iface_table[hash_index]; ++ while (ii) { ++ if ((ii->type != ECM_DB_IFACE_TYPE_MACVLAN) || !ether_addr_equal(ii->type_info.macvlan.address, address)) { ++ ii = ii->hash_next; ++ continue; ++ } ++ ++ _ecm_db_iface_ref(ii); ++ spin_unlock_bh(&ecm_db_lock); ++ DEBUG_TRACE("iface found %px\n", ii); ++ return ii; ++ } ++ spin_unlock_bh(&ecm_db_lock); ++ DEBUG_TRACE("Iface not found\n"); ++ return NULL; ++} ++ ++/* ++ * ecm_db_iface_macvlan_address_get() ++ * Obtain the ethernet address for a macvlan interface ++ */ ++void ecm_db_iface_macvlan_address_get(struct ecm_db_iface_instance *ii, uint8_t *address) ++{ ++ spin_lock_bh(&ecm_db_lock); ++ DEBUG_CHECK_MAGIC(ii, ECM_DB_IFACE_INSTANCE_MAGIC, "%px: magic failed", ii); ++ DEBUG_ASSERT(ii->type == ECM_DB_IFACE_TYPE_MACVLAN, "%px: Bad type, expected macvlan, actual: %d\n", ii, ii->type); ++ ether_addr_copy(address, ii->type_info.macvlan.address); ++ spin_unlock_bh(&ecm_db_lock); ++} ++#endif ++ + #ifdef ECM_INTERFACE_VXLAN_ENABLE + /* + * ecm_db_iface_find_and_ref_vxlan() +@@ -2752,6 +2838,57 @@ void ecm_db_iface_add_ovs_bridge(struct + } + #endif + ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++/* ++ * ecm_db_iface_add_macvlan() ++ * Add a iface instance into the database ++ */ ++void ecm_db_iface_add_macvlan(struct ecm_db_iface_instance *ii, uint8_t *address, char *name, int32_t mtu, ++ int32_t interface_identifier, int32_t ae_interface_identifier, ++ ecm_db_iface_final_callback_t final, void *arg) ++{ ++ ecm_db_iface_hash_t hash_index; ++ struct ecm_db_interface_info_macvlan *type_info; ++ ++ spin_lock_bh(&ecm_db_lock); ++ DEBUG_CHECK_MAGIC(ii, ECM_DB_IFACE_INSTANCE_MAGIC, "%px: magic failed\n", ii); ++ DEBUG_ASSERT(address, "%px: address null\n", ii); ++#ifdef ECM_DB_XREF_ENABLE ++ DEBUG_ASSERT((ii->nodes == NULL) && (ii->node_count == 0), "%px: nodes not null\n", ii); ++#endif ++ DEBUG_ASSERT(!(ii->flags & ECM_DB_IFACE_FLAGS_INSERTED), "%px: inserted\n", ii); ++ DEBUG_ASSERT(name, "%px: no name given\n", ii); ++ spin_unlock_bh(&ecm_db_lock); ++ ++ /* ++ * Record general info ++ */ ++ ii->type = ECM_DB_IFACE_TYPE_MACVLAN; ++#ifdef ECM_STATE_OUTPUT_ENABLE ++ ii->state_get = ecm_db_iface_macvlan_state_get; ++#endif ++ ii->arg = arg; ++ ii->final = final; ++ strlcpy(ii->name, name, IFNAMSIZ); ++ ii->mtu = mtu; ++ ii->interface_identifier = interface_identifier; ++ ii->ae_interface_identifier = ae_interface_identifier; ++ ++ /* ++ * Type specific info ++ */ ++ type_info = &ii->type_info.macvlan; ++ ether_addr_copy(type_info->address, address); ++ ++ /* ++ * Compute hash chain for insertion ++ */ ++ hash_index = ecm_db_iface_generate_hash_index_ethernet(address); ++ ++ ecm_db_iface_add_to_db(ii, hash_index); ++} ++#endif ++ + #ifdef ECM_INTERFACE_VLAN_ENABLE + /* + * ecm_db_iface_add_vlan() +--- a/frontends/nss/ecm_nss_ported_ipv4.c ++++ b/frontends/nss/ecm_nss_ported_ipv4.c +@@ -662,6 +662,21 @@ static void ecm_nss_ported_ipv4_connecti + DEBUG_TRACE("%p: VLAN - unsupported\n", npci); + #endif + break; ++ case ECM_DB_IFACE_TYPE_MACVLAN: ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ ecm_db_iface_macvlan_address_get(ii, from_nss_iface_address); ++ if (is_valid_ether_addr(from_nss_iface_address)) { ++ ether_addr_copy((uint8_t *)nircm->src_mac_rule.flow_src_mac, from_nss_iface_address); ++ nircm->src_mac_rule.mac_valid_flags |= NSS_IPV4_SRC_MAC_FLOW_VALID; ++ nircm->valid_flags |= NSS_IPV4_RULE_CREATE_SRC_MAC_VALID; ++ } ++ ++ DEBUG_TRACE("%px: Macvlan - mac: %pM\n", npci, from_nss_iface_address); ++#else ++ rule_invalid = true; ++ DEBUG_TRACE("%px: MACVLAN - unsupported\n", npci); ++#endif ++ break; + case ECM_DB_IFACE_TYPE_IPSEC_TUNNEL: + #ifdef ECM_INTERFACE_IPSEC_ENABLE + DEBUG_TRACE("%p: IPSEC\n", npci); +@@ -929,6 +944,21 @@ static void ecm_nss_ported_ipv4_connecti + DEBUG_TRACE("%p: VLAN - unsupported\n", npci); + #endif + break; ++ case ECM_DB_IFACE_TYPE_MACVLAN: ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ ecm_db_iface_macvlan_address_get(ii, to_nss_iface_address); ++ if (is_valid_ether_addr(to_nss_iface_address)) { ++ ether_addr_copy((uint8_t *)nircm->src_mac_rule.return_src_mac, to_nss_iface_address); ++ nircm->src_mac_rule.mac_valid_flags |= NSS_IPV4_SRC_MAC_RETURN_VALID; ++ nircm->valid_flags |= NSS_IPV4_RULE_CREATE_SRC_MAC_VALID; ++ } ++ ++ DEBUG_TRACE("%px: Macvlan - mac: %pM\n", npci, to_nss_iface_address); ++#else ++ rule_invalid = true; ++ DEBUG_TRACE("%px: MACVLAN - unsupported\n", npci); ++#endif ++ break; + case ECM_DB_IFACE_TYPE_IPSEC_TUNNEL: + #ifdef ECM_INTERFACE_IPSEC_ENABLE + DEBUG_TRACE("%p: IPSEC\n", npci); +--- a/frontends/nss/ecm_nss_ported_ipv6.c ++++ b/frontends/nss/ecm_nss_ported_ipv6.c +@@ -657,6 +657,21 @@ static void ecm_nss_ported_ipv6_connecti + DEBUG_TRACE("%p: VLAN - unsupported\n", npci); + #endif + break; ++ case ECM_DB_IFACE_TYPE_MACVLAN: ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ ecm_db_iface_macvlan_address_get(ii, from_nss_iface_address); ++ if (is_valid_ether_addr(from_nss_iface_address)) { ++ ether_addr_copy((uint8_t *)nircm->src_mac_rule.flow_src_mac, from_nss_iface_address); ++ nircm->src_mac_rule.mac_valid_flags |= NSS_IPV6_SRC_MAC_FLOW_VALID; ++ nircm->valid_flags |= NSS_IPV6_RULE_CREATE_SRC_MAC_VALID; ++ } ++ ++ DEBUG_TRACE("%px: Macvlan - mac: %pM\n", npci, from_nss_iface_address); ++#else ++ rule_invalid = true; ++ DEBUG_TRACE("%px: MACVLAN - unsupported\n", npci); ++#endif ++ break; + case ECM_DB_IFACE_TYPE_IPSEC_TUNNEL: + #ifdef ECM_INTERFACE_IPSEC_ENABLE + DEBUG_TRACE("%p: IPSEC\n", npci); +@@ -899,6 +914,21 @@ static void ecm_nss_ported_ipv6_connecti + DEBUG_TRACE("%p: VLAN - unsupported\n", npci); + #endif + break; ++ case ECM_DB_IFACE_TYPE_MACVLAN: ++#ifdef ECM_INTERFACE_MACVLAN_ENABLE ++ ecm_db_iface_macvlan_address_get(ii, to_nss_iface_address); ++ if (is_valid_ether_addr(to_nss_iface_address)) { ++ ether_addr_copy((uint8_t *)nircm->src_mac_rule.return_src_mac, to_nss_iface_address); ++ nircm->src_mac_rule.mac_valid_flags |= NSS_IPV6_SRC_MAC_RETURN_VALID; ++ nircm->valid_flags |= NSS_IPV6_RULE_CREATE_SRC_MAC_VALID; ++ } ++ ++ DEBUG_TRACE("%px: Macvlan - mac: %pM\n", npci, to_nss_iface_address); ++#else ++ rule_invalid = true; ++ DEBUG_TRACE("%px: MACVLAN - unsupported\n", npci); ++#endif ++ break; + case ECM_DB_IFACE_TYPE_IPSEC_TUNNEL: + #ifdef ECM_INTERFACE_IPSEC_ENABLE + DEBUG_TRACE("%p: IPSEC\n", npci);