--- a/Makefile +++ b/Makefile @@ -5,27 +5,25 @@ ccflags-y := -I$(obj) -I$(obj)/.. export BUILD_ID = \"Build Id: $(shell date +'%m/%d/%y, %H:%M:%S')\" ccflags-y += -DNSS_CLIENT_BUILD_ID="$(BUILD_ID)" +qca-nss-tunipip6-objs := nss_connmgr_tunipip6.o qca-nss-tun6rd-objs := nss_connmgr_tun6rd.o +ccflags-y += -DNSS_TUNIPIP6_DEBUG_LEVEL=0 ccflags-y += -DNSS_TUN6RD_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror - -KERNELVERSION := $(word 1, $(subst ., ,$(KERNELVERSION))).$(word 2, $(subst ., ,$(KERNELVERSION))) +ccflags-y += -Werror obj-$(bridge-mgr)+= bridge/ obj-$(capwapmgr)+= capwapmgr/ obj-$(dtlsmgr)+= dtls/$(DTLSMGR_DIR)/ obj-$(gre)+= gre/ obj-$(ipsecmgr)+= ipsecmgr/$(IPSECMGR_DIR)/ -obj-$(ipsecmgr-klips)+= ipsecmgr/$(IPSECMGR_DIR)/plugins/klips/ -obj-$(ipsecmgr-xfrm)+= ipsecmgr/$(IPSECMGR_DIR)/plugins/xfrm/ obj-$(l2tpv2)+= l2tp/l2tpv2/ obj-$(lag-mgr)+= lag/ obj-$(map-t)+= map/map-t/ obj-$(portifmgr)+= portifmgr/ obj-$(pptp)+= pptp/ obj-$(profile)+= profiler/ -obj-$(tunipip6)+= tunipip6/ +obj-$(tunipip6)+= qca-nss-tunipip6.o obj-$(tun6rd)+= qca-nss-tun6rd.o obj-$(qdisc)+= nss_qdisc/ obj-$(vlan-mgr)+= vlan/ @@ -38,8 +36,6 @@ obj-$(clmapmgr)+= clmapmgr/ obj-$(match)+= match/ obj-$(tlsmgr)+= tls/ obj-$(mirror)+= mirror/ -obj-$(mscs)+= mscs/ -obj-$(wifi-meshmgr)+= wifi_meshmgr/ #NSS NETLINK obj-$(netlink)+= netlink/ --- a/bridge/Makefile +++ b/bridge/Makefile @@ -9,7 +9,7 @@ qca-nss-bridge-mgr-objs += nss_bridge_mg endif ccflags-y += -DNSS_BRIDGE_MGR_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror +ccflags-y += -Werror ifeq ($(SoC),$(filter $(SoC),ipq807x ipq807x_64 ipq60xx ipq60xx_64)) ccflags-y += -DNSS_BRIDGE_MGR_PPE_SUPPORT --- a/bridge/nss_bridge_mgr.c +++ b/bridge/nss_bridge_mgr.c @@ -1,12 +1,9 @@ /* ************************************************************************** - * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. - * + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. - * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -418,37 +415,6 @@ static int nss_bridge_mgr_del_bond_slave } /* - * nss_bridge_mgr_bond_fdb_join() - * Update FDB state when a bond interface joining bridge. - */ -static int nss_bridge_mgr_bond_fdb_join(struct nss_bridge_pvt *b_pvt) -{ - /* - * If already other bond devices are attached to bridge, - * only increment bond_slave_num, - */ - spin_lock(&br_mgr_ctx.lock); - if (b_pvt->bond_slave_num) { - b_pvt->bond_slave_num++; - spin_unlock(&br_mgr_ctx.lock); - return NOTIFY_DONE; - } - b_pvt->bond_slave_num = 1; - spin_unlock(&br_mgr_ctx.lock); - - /* - * This is the first bond device being attached to bridge. In order to enforce Linux - * bond slave selection in bridge flows involving bond interfaces, we need to disable - * fdb learning on this bridge master to allow flow based bridging. - */ - if (nss_bridge_mgr_disable_fdb_learning(b_pvt) < 0) { - return NOTIFY_BAD; - } - - return NOTIFY_DONE; -} - -/* * nss_bridge_mgr_bond_master_join() * Add a bond interface to bridge */ @@ -481,7 +447,28 @@ static int nss_bridge_mgr_bond_master_jo } } - if (nss_bridge_mgr_bond_fdb_join(b_pvt) == NOTIFY_DONE) { + /* + * If already other bond devices are attached to bridge, + * only increment bond_slave_num, + */ + spin_lock(&br_mgr_ctx.lock); + if (b_pvt->bond_slave_num) { + b_pvt->bond_slave_num++; + spin_unlock(&br_mgr_ctx.lock); + return NOTIFY_DONE; + } + spin_unlock(&br_mgr_ctx.lock); + + /* + * This is the first bond device being attached to bridge. In order to enforce Linux + * bond slave selection in bridge flows involving bond interfaces, we need to disable + * fdb learning on this bridge master to allow flow based bridging. + */ + if (!nss_bridge_mgr_disable_fdb_learning(b_pvt)) { + spin_lock(&br_mgr_ctx.lock); + b_pvt->bond_slave_num = 1; + spin_unlock(&br_mgr_ctx.lock); + return NOTIFY_DONE; } @@ -501,40 +488,6 @@ cleanup: } /* - * nss_bridge_mgr_bond_fdb_leave() - * Update FDB state when a bond interface leaving bridge. - */ -static int nss_bridge_mgr_bond_fdb_leave(struct nss_bridge_pvt *b_pvt) -{ - - nss_bridge_mgr_assert(b_pvt->bond_slave_num == 0); - - /* - * If more than one bond devices are attached to bridge, - * only decrement the bond_slave_num - */ - spin_lock(&br_mgr_ctx.lock); - if (b_pvt->bond_slave_num > 1) { - b_pvt->bond_slave_num--; - spin_unlock(&br_mgr_ctx.lock); - return NOTIFY_DONE; - } - b_pvt->bond_slave_num = 0; - spin_unlock(&br_mgr_ctx.lock); - - /* - * The last bond interface is removed from bridge, we can switch back to FDB - * learning mode. - */ - if (nss_bridge_mgr_enable_fdb_learning(b_pvt) < 0) { - return NOTIFY_BAD; - } - - return NOTIFY_DONE; -} - - -/* * nss_bridge_mgr_bond_master_leave() * Remove a bond interface from bridge */ @@ -563,7 +516,27 @@ static int nss_bridge_mgr_bond_master_le } } - if (nss_bridge_mgr_bond_fdb_leave(b_pvt) == NOTIFY_DONE) { + /* + * If more than one bond devices are attached to bridge, + * only decrement the bond_slave_num + */ + spin_lock(&br_mgr_ctx.lock); + if (b_pvt->bond_slave_num > 1) { + b_pvt->bond_slave_num--; + spin_unlock(&br_mgr_ctx.lock); + return NOTIFY_DONE; + } + spin_unlock(&br_mgr_ctx.lock); + + /* + * The last bond interface is removed from bridge, we can switch back to FDB + * learning mode. + */ + if (!nss_bridge_mgr_enable_fdb_learning(b_pvt)) { + spin_lock(&br_mgr_ctx.lock); + b_pvt->bond_slave_num = 0; + spin_unlock(&br_mgr_ctx.lock); + return NOTIFY_DONE; } @@ -782,6 +755,10 @@ int nss_bridge_mgr_join_bridge(struct ne * This is done by not sending join message to the bridge in NSS. */ if (br_mgr_ctx.wan_if_num == ifnum) { + if (!nss_bridge_mgr_l2_exception_acl_enable()) { + nss_bridge_mgr_warn("%px: failed to enable ACL\n", br); + return -EIO; + } br->wan_if_enabled = true; br->wan_if_num = ifnum; nss_bridge_mgr_info("if_num %d is added as WAN interface \n", ifnum); @@ -830,10 +807,9 @@ int nss_bridge_mgr_join_bridge(struct ne } /* - * Update FDB state of the bridge. No need to add individual interfaces of bond to the bridge. - * VLAN interface verifies that all interfaces are physical so, no need to verify again. + * Add the bond_master to bridge. */ - if (nss_bridge_mgr_bond_fdb_join(br) != NOTIFY_DONE) { + if (nss_bridge_mgr_bond_master_join(real_dev, br) != NOTIFY_DONE) { nss_bridge_mgr_warn("%px: Slaves of bond interface %s join bridge failed\n", br, real_dev->name); nss_bridge_tx_leave_msg(br->ifnum, dev); nss_vlan_mgr_leave_bridge(dev, br->vsi); @@ -888,6 +864,7 @@ int nss_bridge_mgr_leave_bridge(struct n * Hence a leave message should also be avaoided. */ if ((br->wan_if_enabled) && (br->wan_if_num == ifnum)) { + nss_bridge_mgr_l2_exception_acl_disable(); br->wan_if_enabled = false; br->wan_if_num = -1; nss_bridge_mgr_info("if_num %d is added as WAN interface\n", ifnum); @@ -933,10 +910,9 @@ int nss_bridge_mgr_leave_bridge(struct n } /* - * Update FDB state of the bridge. No need to add individual interfaces of bond to the bridge. - * VLAN interface verifies that all interfaces are physical so, no need to verify again. + * Remove the bond_master from bridge. */ - if (nss_bridge_mgr_bond_fdb_leave(br) != NOTIFY_DONE) { + if (nss_bridge_mgr_bond_master_leave(real_dev, br) != NOTIFY_DONE) { nss_bridge_mgr_warn("%px: Slaves of bond interface %s leave bridge failed\n", br, real_dev->name); nss_vlan_mgr_join_bridge(dev, br->vsi); nss_bridge_tx_join_msg(br->ifnum, dev); @@ -1046,45 +1022,44 @@ int nss_bridge_mgr_register_br(struct ne b_pvt->dev = dev; -#if defined(NSS_BRIDGE_MGR_PPE_SUPPORT) - err = ppe_vsi_alloc(NSS_BRIDGE_MGR_SWITCH_ID, &vsi_id); - if (err) { - nss_bridge_mgr_warn("%px: failed to alloc bridge vsi, error = %d\n", b_pvt, err); - goto fail; - } - - b_pvt->vsi = vsi_id; -#endif - ifnum = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_BRIDGE); if (ifnum < 0) { nss_bridge_mgr_warn("%px: failed to alloc bridge di\n", b_pvt); - goto fail_1; + nss_bridge_mgr_delete_instance(b_pvt); + return -EFAULT; } if (!nss_bridge_register(ifnum, dev, NULL, NULL, 0, b_pvt)) { nss_bridge_mgr_warn("%px: failed to register bridge di to NSS\n", b_pvt); - goto fail_2; + goto fail; } #if defined(NSS_BRIDGE_MGR_PPE_SUPPORT) + err = ppe_vsi_alloc(NSS_BRIDGE_MGR_SWITCH_ID, &vsi_id); + if (err) { + nss_bridge_mgr_warn("%px: failed to alloc bridge vsi, error = %d\n", b_pvt, err); + goto fail_1; + } + + b_pvt->vsi = vsi_id; + err = nss_bridge_tx_vsi_assign_msg(ifnum, vsi_id); if (err != NSS_TX_SUCCESS) { nss_bridge_mgr_warn("%px: failed to assign vsi msg, error = %d\n", b_pvt, err); - goto fail_3; + goto fail_2; } #endif err = nss_bridge_tx_set_mac_addr_msg(ifnum, dev->dev_addr); if (err != NSS_TX_SUCCESS) { nss_bridge_mgr_warn("%px: failed to set mac_addr msg, error = %d\n", b_pvt, err); - goto fail_4; + goto fail_3; } err = nss_bridge_tx_set_mtu_msg(ifnum, dev->mtu); if (err != NSS_TX_SUCCESS) { nss_bridge_mgr_warn("%px: failed to set mtu msg, error = %d\n", b_pvt, err); - goto fail_4; + goto fail_3; } /* @@ -1092,8 +1067,10 @@ int nss_bridge_mgr_register_br(struct ne */ b_pvt->ifnum = ifnum; b_pvt->mtu = dev->mtu; +#if defined(NSS_BRIDGE_MGR_PPE_SUPPORT) b_pvt->wan_if_num = -1; b_pvt->wan_if_enabled = false; +#endif ether_addr_copy(b_pvt->dev_addr, dev->dev_addr); spin_lock(&br_mgr_ctx.lock); list_add(&b_pvt->list, &br_mgr_ctx.list); @@ -1110,29 +1087,25 @@ int nss_bridge_mgr_register_br(struct ne #endif return 0; -fail_4: +fail_3: #if defined(NSS_BRIDGE_MGR_PPE_SUPPORT) if (nss_bridge_tx_vsi_unassign_msg(ifnum, vsi_id) != NSS_TX_SUCCESS) { nss_bridge_mgr_warn("%px: failed to unassign vsi\n", b_pvt); } -fail_3: -#endif +fail_2: + ppe_vsi_free(NSS_BRIDGE_MGR_SWITCH_ID, vsi_id); + +fail_1: +#endif nss_bridge_unregister(ifnum); -fail_2: +fail: if (nss_dynamic_interface_dealloc_node(ifnum, NSS_DYNAMIC_INTERFACE_TYPE_BRIDGE) != NSS_TX_SUCCESS) { nss_bridge_mgr_warn("%px: failed to dealloc bridge di\n", b_pvt); } -fail_1: -#if defined(NSS_BRIDGE_MGR_PPE_SUPPORT) - ppe_vsi_free(NSS_BRIDGE_MGR_SWITCH_ID, vsi_id); -fail: -#endif - nss_bridge_mgr_delete_instance(b_pvt); - return -EFAULT; } @@ -1159,6 +1132,7 @@ static int nss_bridge_mgr_bond_slave_cha return NOTIFY_DONE; } +#if defined(NSS_BRIDGE_MGR_PPE_SUPPORT) /* * Add or remove the slave based based on linking event */ @@ -1173,6 +1147,7 @@ static int nss_bridge_mgr_bond_slave_cha cu_info->upper_dev->name, master->name); } } +#endif return NOTIFY_DONE; } @@ -1200,7 +1175,7 @@ static int nss_bridge_mgr_changemtu_even if (nss_bridge_tx_set_mtu_msg(b_pvt->ifnum, dev->mtu) != NSS_TX_SUCCESS) { nss_bridge_mgr_warn("%px: Failed to send change MTU message to NSS\n", b_pvt); - return NOTIFY_DONE; + return NOTIFY_BAD; } spin_lock(&br_mgr_ctx.lock); @@ -1234,7 +1209,7 @@ static int nss_bridge_mgr_changeaddr_eve if (nss_bridge_tx_set_mac_addr_msg(b_pvt->ifnum, dev->dev_addr) != NSS_TX_SUCCESS) { nss_bridge_mgr_warn("%px: Failed to send change MAC address message to NSS\n", b_pvt); - return NOTIFY_DONE; + return NOTIFY_BAD; } spin_lock(&br_mgr_ctx.lock); @@ -1294,6 +1269,7 @@ static int nss_bridge_mgr_changeupper_ev nss_bridge_mgr_trace("%px: Interface %s joining bridge %s\n", b_pvt, dev->name, master_dev->name); if (nss_bridge_mgr_join_bridge(dev, b_pvt)) { nss_bridge_mgr_warn("%px: Interface %s failed to join bridge %s\n", b_pvt, dev->name, master_dev->name); + return NOTIFY_BAD; } return NOTIFY_DONE; @@ -1302,6 +1278,7 @@ static int nss_bridge_mgr_changeupper_ev nss_bridge_mgr_trace("%px: Interface %s leaving bridge %s\n", b_pvt, dev->name, master_dev->name); if (nss_bridge_mgr_leave_bridge(dev, b_pvt)) { nss_bridge_mgr_warn("%px: Interface %s failed to leave bridge %s\n", b_pvt, dev->name, master_dev->name); + return NOTIFY_BAD; } return NOTIFY_DONE; @@ -1627,14 +1604,6 @@ int __init nss_bridge_mgr_init_module(vo br_mgr_ctx.wan_if_num = -1; br_fdb_update_register_notify(&nss_bridge_mgr_fdb_update_notifier); br_mgr_ctx.nss_bridge_mgr_header = register_sysctl_table(nss_bridge_mgr_root_dir); - - /* - * Enable ACL rule to enable L2 exception. This is needed if PPE Virtual ports is added to bridge. - * It is assumed that VP is using flow based bridging, hence L2 exceptions will need to be enabled on PPE bridge. - */ - if (!nss_bridge_mgr_l2_exception_acl_enable()) { - nss_bridge_mgr_warn("Failed to enable ACL\n"); - } #endif #if defined (NSS_BRIDGE_MGR_OVS_ENABLE) nss_bridge_mgr_ovs_init(); @@ -1656,12 +1625,6 @@ void __exit nss_bridge_mgr_exit_module(v if (br_mgr_ctx.nss_bridge_mgr_header) { unregister_sysctl_table(br_mgr_ctx.nss_bridge_mgr_header); } - - /* - * Disable the PPE L2 exceptions which were enabled during module init for PPE virtual ports. - */ - nss_bridge_mgr_l2_exception_acl_disable(); - #endif #if defined (NSS_BRIDGE_MGR_OVS_ENABLE) nss_bridge_mgr_ovs_exit(); --- a/capwapmgr/Makefile +++ b/capwapmgr/Makefile @@ -14,4 +14,4 @@ qca-nss-capwapmgr-objs := nss_capwapmgr. ccflags-y += -DNSS_CAPWAPMGR_DEBUG_LEVEL=6 ccflags-y += $(NSS_CCFLAGS) -DNSS_DEBUG_LEVEL=0 -DNSS_PKT_STATS_ENABLED=0 -ccflags-y += -Wall -Werror +ccflags-y += -Werror --- a/capwapmgr/nss_capwapmgr.c +++ b/capwapmgr/nss_capwapmgr.c @@ -1,12 +1,9 @@ /* ************************************************************************** - * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. - * + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. - * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -95,16 +92,17 @@ #define NSS_CAPWAPMGR_BIND_BITMAP 0x7E /* - * We need 4 ACL rules - 2 rules for each v4 and v6 classification. + * The number of rules supported by a list is 4. Since we need 2 rules for every + * dscp classification (v4 and v6). We set this value to 2. */ -#define NSS_CAPWAPMGR_ACL_RULES_PER_LIST 4 +#define NSS_CAPWAPMGR_ACL_RULES_PER_LIST 2 /* - * We currently have list-id 60 reserved for this purpose. + * We currently have list-id 60 and 61 reserved for this purpose. * TODO: Find a better approach to reserve list-id. */ #define NSS_CAPWAPMGR_ACL_LIST_START 60 -#define NSS_CAPWAPMGR_ACL_LIST_CNT 1 +#define NSS_CAPWAPMGR_ACL_LIST_CNT 2 #define NSS_CAPWAPMGR_NORMAL_FRAME_MTU 1500 @@ -234,7 +232,7 @@ static void nss_capwapmgr_decongestion_c /* * nss_capwapmgr_start_xmit() - * Transmit's skb to NSS FW over CAPWAP if_num_inner. + * Transmit's skb to NSS FW over CAPWAP if_num. * * Please make sure to leave headroom of NSS_CAPWAP_HEADROOM with every * packet so that NSS can encap eth,vlan,ip,udp,capwap headers. @@ -246,7 +244,7 @@ static netdev_tx_t nss_capwapmgr_start_x struct net_device_stats *stats = &dev->stats; struct nss_capwapmgr_priv *priv; struct nss_capwap_metaheader *pre; - uint32_t if_num_inner; + uint32_t if_num; nss_tx_status_t status; priv = netdev_priv(dev); @@ -259,9 +257,9 @@ static netdev_tx_t nss_capwapmgr_start_x return NETDEV_TX_OK; } - if_num_inner = priv->tunnel[pre->tunnel_id].if_num_inner; - if (unlikely(if_num_inner == -1)) { - nss_capwapmgr_warn("%px: (CAPWAP packet) if_num_inner in the tunnel not set pre->tunnel_id %d\n", dev, + if_num = priv->tunnel[pre->tunnel_id].if_num; + if (unlikely(if_num == 0)) { + nss_capwapmgr_warn("%px: (CAPWAP packet) if_num in the tunnel not set pre->tunnel_id %d\n", dev, pre->tunnel_id); kfree_skb(skb); stats->tx_dropped++; @@ -277,7 +275,7 @@ static netdev_tx_t nss_capwapmgr_start_x */ skb_set_queue_mapping(skb, pre->flow_id & 0x1); - status = nss_capwap_tx_buf(priv->nss_ctx, skb, if_num_inner); + status = nss_capwap_tx_buf(priv->nss_ctx, skb, if_num); if (unlikely(status != NSS_TX_SUCCESS)) { if (status == NSS_TX_FAILURE_QUEUE) { nss_capwapmgr_warn("%px: netdev :%px queue is full", dev, dev); @@ -302,7 +300,7 @@ static void nss_capwapmgr_fill_up_stats( stats->rx_dropped += tstats->pnode_stats.rx_dropped; /* rx_fifo_errors will appear as rx overruns in ifconfig */ - stats->rx_fifo_errors += (tstats->rx_n2h_drops + tstats->rx_n2h_queue_full_drops); + stats->rx_fifo_errors += (tstats->rx_queue_full_drops + tstats->rx_n2h_queue_full_drops); stats->rx_errors += (tstats->rx_mem_failure_drops + tstats->rx_oversize_drops + tstats->rx_frag_timeout_drops); stats->rx_bytes += tstats->pnode_stats.rx_bytes; @@ -370,6 +368,20 @@ static void nss_capwapmgr_dev_tunnel_sta } #endif +/** + * nss_capwapmgr_change_mtu - set new MTU size + * @dev: network device + * @new_mtu: new Maximum Transfer Unit + * + * Allow changing MTU size. Needs to be overridden for devices + * supporting jumbo frames. + */ +int nss_capwapmgr_change_mtu(struct net_device *dev, int new_mtu) +{ + dev->mtu = new_mtu; + return 0; +} + /* * nss_capwapmgr_netdev_ops * Netdev operations. @@ -379,7 +391,7 @@ static const struct net_device_ops nss_c .ndo_stop = nss_capwapmgr_close, .ndo_start_xmit = nss_capwapmgr_start_xmit, .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, + .ndo_change_mtu = nss_capwapmgr_change_mtu, .ndo_get_stats64 = nss_capwapmgr_dev_tunnel_stats, }; @@ -559,12 +571,15 @@ static struct nss_capwapmgr_tunnel *nss_ return NULL; } + dev_hold(dev); priv = netdev_priv(dev); t = &priv->tunnel[tunnel_id]; - if ( (t->if_num_inner == -1) || (t->if_num_outer == -1) ) { + if (t->if_num == 0) { + dev_put(dev); return NULL; } + dev_put(dev); return t; } @@ -607,10 +622,6 @@ struct net_device *nss_capwapmgr_netdev_ goto fail1; } memset(priv->tunnel, 0, sizeof(struct nss_capwapmgr_tunnel) * NSS_CAPWAPMGR_MAX_TUNNELS); - for (i = 0; i < NSS_CAPWAPMGR_MAX_TUNNELS; i++) { - priv->tunnel[i].if_num_inner = -1; - priv->tunnel[i].if_num_outer = -1; - } priv->resp = kmalloc(sizeof(struct nss_capwapmgr_response) * NSS_MAX_DYNAMIC_INTERFACES, GFP_ATOMIC); if (!priv->resp) { @@ -870,10 +881,6 @@ static nss_tx_status_t nss_capwapmgr_cre memcpy(nircm->conn_rule.return_mac, unic->dest_mac, 6); } - nircm->valid_flags |= NSS_IPV4_RULE_CREATE_SRC_MAC_VALID; - nircm->src_mac_rule.mac_valid_flags |=NSS_IPV4_SRC_MAC_FLOW_VALID; - memcpy(nircm->src_mac_rule.flow_src_mac, nircm->conn_rule.return_mac, 6); - /* * Copy over the DSCP rule parameters */ @@ -1009,10 +1016,6 @@ static nss_tx_status_t nss_capwapmgr_cre memcpy(nircm->conn_rule.return_mac, unic->dest_mac, 6); nircm->valid_flags |= NSS_IPV6_RULE_CREATE_CONN_VALID; - nircm->valid_flags |= NSS_IPV6_RULE_CREATE_SRC_MAC_VALID; - nircm->src_mac_rule.mac_valid_flags |=NSS_IPV6_SRC_MAC_FLOW_VALID; - memcpy(nircm->src_mac_rule.flow_src_mac, nircm->conn_rule.return_mac, 6); - /* * Copy over the DSCP rule parameters */ @@ -1294,85 +1297,23 @@ static nss_capwapmgr_status_t nss_capwap } /* - * nss_capwapmgr_tx_msg_enable_tunnel() - * Common function to send CAPWAP tunnel enable msg - */ -static nss_tx_status_t nss_capwapmgr_tx_msg_enable_tunnel(struct nss_ctx_instance *ctx, struct net_device *dev, uint32_t if_num, uint32_t sibling_if_num) -{ - struct nss_capwap_msg capwapmsg; - nss_tx_status_t status; - - /* - * Prepare the tunnel configuration parameter to send to NSS FW - */ - memset(&capwapmsg, 0, sizeof(struct nss_capwap_msg)); - capwapmsg.msg.enable_tunnel.sibling_if_num = sibling_if_num; - - /* - * Send CAPWAP data tunnel command to NSS - */ - nss_capwap_msg_init(&capwapmsg, if_num, NSS_CAPWAP_MSG_TYPE_ENABLE_TUNNEL, sizeof(struct nss_capwap_enable_tunnel_msg), nss_capwapmgr_msg_event_receive, dev); - - status = nss_capwapmgr_tx_msg_sync(ctx, dev, &capwapmsg); - if (status != NSS_TX_SUCCESS) { - nss_capwapmgr_warn("%px: ctx: CMD: %d Tunnel error : %d \n", ctx, NSS_CAPWAP_MSG_TYPE_ENABLE_TUNNEL, status); - } - - return status; -} - -/* - * nss_capwapmgr_tunnel_action() - * Common function for CAPWAP tunnel operation messages without - * any message data structures. - */ -static nss_tx_status_t nss_capwapmgr_tunnel_action(struct nss_ctx_instance *ctx, struct net_device *dev, uint32_t if_num, nss_capwap_msg_type_t cmd) -{ - struct nss_capwap_msg capwapmsg; - nss_tx_status_t status; - - /* - * Prepare the tunnel configuration parameter to send to NSS FW - */ - memset(&capwapmsg, 0, sizeof(struct nss_capwap_msg)); - - /* - * Send CAPWAP data tunnel command to NSS - */ - nss_capwap_msg_init(&capwapmsg, if_num, cmd, 0, nss_capwapmgr_msg_event_receive, dev); - - status = nss_capwapmgr_tx_msg_sync(ctx, dev, &capwapmsg); - if (status != NSS_TX_SUCCESS) { - nss_capwapmgr_warn("%px: ctx: CMD: %d Tunnel error : %d \n", ctx, cmd, status); - } - - return status; -} - -/* * nss_capwapmgr_get_dtls_netdev() * API for getting the dtls netdev associated to the capwap tunnel - * - * The caller is expected to do a dev_put() to release the reference. */ struct net_device *nss_capwapmgr_get_dtls_netdev(struct net_device *capwap_dev, uint8_t tunnel_id) { struct nss_capwapmgr_tunnel *t; struct net_device *dtls_dev; - dev_hold(capwap_dev); t = nss_capwapmgr_verify_tunnel_param(capwap_dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: can't find tunnel: %d\n", capwap_dev, tunnel_id); - dev_put(capwap_dev); return NULL; } dtls_dev = t->dtls_dev; - dev_hold(dtls_dev); - - dev_put(capwap_dev); + dev_hold(dtls_dev); return dtls_dev; } EXPORT_SYMBOL(nss_capwapmgr_get_dtls_netdev); @@ -1394,16 +1335,15 @@ nss_capwapmgr_status_t nss_capwapmgr_upd return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: can't find tunnel: %d\n", dev, tunnel_id); - dev_put(dev); return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } + dev_hold(dev); priv = netdev_priv(dev); - nss_capwapmgr_info("%px: %d: tunnel update MTU is being called\n", dev, t->if_num_inner); + nss_capwapmgr_info("%px: %d: tunnel update MTU is being called\n", dev, t->if_num); /* * Prepare the tunnel configuration parameter to send to NSS FW @@ -1413,7 +1353,7 @@ nss_capwapmgr_status_t nss_capwapmgr_upd /* * Send CAPWAP data tunnel command to NSS */ - nss_capwap_msg_init(&capwapmsg, t->if_num_inner, NSS_CAPWAP_MSG_TYPE_UPDATE_PATH_MTU, + nss_capwap_msg_init(&capwapmsg, t->if_num, NSS_CAPWAP_MSG_TYPE_UPDATE_PATH_MTU, sizeof(struct nss_capwap_path_mtu_msg), nss_capwapmgr_msg_event_receive, dev); capwapmsg.msg.mtu.path_mtu = htonl(mtu); status = nss_capwapmgr_tx_msg_sync(priv->nss_ctx, dev, &capwapmsg); @@ -1473,22 +1413,20 @@ nss_capwapmgr_status_t nss_capwapmgr_upd { struct nss_capwapmgr_priv *priv; struct nss_capwapmgr_tunnel *t; + nss_capwapmgr_status_t status; nss_tx_status_t nss_status; - nss_capwapmgr_status_t status = NSS_CAPWAPMGR_SUCCESS; struct nss_ipv6_create *v6; uint8_t mac_addr_old[ETH_ALEN]; - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: can't find tunnel: %d\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } - + dev_hold(dev); priv = netdev_priv(dev); - nss_capwapmgr_info("%px: %d: tunnel update mac Addr is being called\n", dev, tunnel_id); + nss_capwapmgr_info("%px: %d: tunnel update mac Addr is being called\n", dev, t->if_num); /* * Update the IPv4/IPv6 rule with the new destination mac address for flow and return. @@ -1505,10 +1443,11 @@ nss_capwapmgr_status_t nss_capwapmgr_upd if (nss_status != NSS_TX_SUCCESS) { nss_capwapmgr_warn("%px: Update Destination Mac for tunnel error : %d \n", dev, nss_status); memcpy(t->ip_rule.v4.src_mac, mac_addr_old, ETH_ALEN); - status = NSS_CAPWAPMGR_FAILURE_IP_RULE; } - goto done; + dev_put(dev); + return status; + } v6 = &t->ip_rule.v6; @@ -1519,10 +1458,10 @@ nss_capwapmgr_status_t nss_capwapmgr_upd if (nss_status != NSS_TX_SUCCESS) { nss_capwapmgr_warn("%px: Update Destination Mac for tunnel error : %d \n", dev, nss_status); memcpy(t->ip_rule.v6.src_mac, mac_addr_old, ETH_ALEN); - status = NSS_CAPWAPMGR_FAILURE_IP_RULE; + dev_put(dev); + return NSS_CAPWAPMGR_FAILURE_IP_RULE; } -done: dev_put(dev); return status; } @@ -1532,24 +1471,23 @@ EXPORT_SYMBOL(nss_capwapmgr_update_dest_ * nss_capwapmgr_update_src_interface() * API for updating Source Interface */ -nss_capwapmgr_status_t nss_capwapmgr_update_src_interface(struct net_device *dev, uint8_t tunnel_id, uint32_t src_interface_num) +nss_capwapmgr_status_t nss_capwapmgr_update_src_interface(struct net_device *dev, uint8_t tunnel_id, int32_t src_interface_num) { struct nss_capwapmgr_priv *priv; struct nss_capwapmgr_tunnel *t; + nss_capwapmgr_status_t status; nss_tx_status_t nss_status; uint32_t outer_trustsec_enabled, dtls_enabled, forward_if_num, src_interface_num_temp; - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: can't find tunnel: %d\n", dev, tunnel_id); - dev_put(dev); return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } - + dev_hold(dev); priv = netdev_priv(dev); - nss_capwapmgr_info("%px: %d: tunnel update source interface is being called\n", dev, tunnel_id); + nss_capwapmgr_info("%px: %d: tunnel update source interface is being called\n", dev, t->if_num); outer_trustsec_enabled = t->capwap_rule.enabled_features & NSS_CAPWAPMGR_FEATURE_OUTER_TRUSTSEC_ENABLED; dtls_enabled = t->capwap_rule.enabled_features & NSS_CAPWAPMGR_FEATURE_DTLS_ENABLED; @@ -1558,7 +1496,7 @@ nss_capwapmgr_status_t nss_capwapmgr_upd */ if (outer_trustsec_enabled) { if (!dtls_enabled) { - forward_if_num = nss_capwap_ifnum_with_core_id(t->if_num_outer); + forward_if_num = nss_capwap_ifnum_with_core_id(t->if_num); } else { forward_if_num = nss_dtlsmgr_get_interface(t->dtls_dev, NSS_DTLSMGR_INTERFACE_TYPE_OUTER); } @@ -1566,7 +1504,6 @@ nss_capwapmgr_status_t nss_capwapmgr_upd nss_status = nss_trustsec_tx_update_nexthop(forward_if_num, src_interface_num, t->capwap_rule.outer_sgt_value); if (nss_status != NSS_TX_SUCCESS) { nss_capwapmgr_warn("%px: unconfigure trustsec_tx failed\n", dev); - dev_put(dev); return NSS_CAPWAPMGR_FAILURE_UNCONFIGURE_TRUSTSEC_TX; } @@ -1575,7 +1512,6 @@ nss_capwapmgr_status_t nss_capwapmgr_upd } else { t->ip_rule.v6.src_interface_num = src_interface_num; } - dev_put(dev); return NSS_CAPWAPMGR_SUCCESS; } @@ -1659,8 +1595,7 @@ nss_capwapmgr_status_t nss_capwapmgr_upd } } t->tunnel_state |= NSS_CAPWAPMGR_TUNNEL_STATE_IPRULE_CONFIGURED; - dev_put(dev); - return NSS_CAPWAPMGR_SUCCESS; + return status; } EXPORT_SYMBOL(nss_capwapmgr_update_src_interface); @@ -1997,7 +1932,7 @@ EXPORT_SYMBOL(nss_capwapmgr_dscp_rule_cr nss_capwapmgr_status_t nss_capwapmgr_configure_dtls(struct net_device *dev, uint8_t tunnel_id, uint8_t enable_dtls, struct nss_dtlsmgr_config *in_data) { struct nss_capwapmgr_priv *priv; - struct nss_capwap_msg capwapmsg_inner, capwapmsg_outer; + struct nss_capwap_msg capwapmsg; struct nss_capwapmgr_tunnel *t; struct nss_ipv4_destroy v4; struct nss_ipv6_destroy v6; @@ -2005,11 +1940,9 @@ nss_capwapmgr_status_t nss_capwapmgr_con nss_capwapmgr_status_t status; uint32_t ip_if_num, dtls_enabled, outer_trustsec_enabled; - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: can't find tunnel: %d\n", dev, tunnel_id); - dev_put(dev); return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } @@ -2017,7 +1950,6 @@ nss_capwapmgr_status_t nss_capwapmgr_con dtls_enabled = t->capwap_rule.enabled_features & NSS_CAPWAPMGR_FEATURE_DTLS_ENABLED; if ((enable_dtls && dtls_enabled) || (!enable_dtls && !dtls_enabled)) { nss_capwapmgr_warn("%px: nothing changed for tunnel: %d\n", dev, tunnel_id); - dev_put(dev); return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } @@ -2027,31 +1959,23 @@ nss_capwapmgr_status_t nss_capwapmgr_con */ if (t->tunnel_state & NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED) { nss_capwapmgr_warn("%px: tunnel %d is already enabled\n", dev, tunnel_id); - dev_put(dev); return NSS_CAPWAPMGR_FAILURE_TUNNEL_ENABLED; } /* * Prepare DTLS configure message */ - memset(&capwapmsg_inner, 0, sizeof(struct nss_capwap_msg)); - nss_capwap_msg_init(&capwapmsg_inner, t->if_num_inner, NSS_CAPWAP_MSG_TYPE_DTLS, - sizeof(struct nss_capwap_dtls_msg), nss_capwapmgr_msg_event_receive, dev); - - memset(&capwapmsg_outer, 0, sizeof(struct nss_capwap_msg)); - nss_capwap_msg_init(&capwapmsg_outer, t->if_num_outer, NSS_CAPWAP_MSG_TYPE_DTLS, + memset(&capwapmsg, 0, sizeof(struct nss_capwap_msg)); + nss_capwap_msg_init(&capwapmsg, t->if_num, NSS_CAPWAP_MSG_TYPE_DTLS, sizeof(struct nss_capwap_dtls_msg), nss_capwapmgr_msg_event_receive, dev); - if (!enable_dtls) { nss_capwapmgr_info("%px disabling DTLS for tunnel: %d\n", dev, tunnel_id); - ip_if_num = nss_capwap_ifnum_with_core_id(t->if_num_outer); - capwapmsg_inner.msg.dtls.enable = 0; - capwapmsg_inner.msg.dtls.dtls_inner_if_num = t->capwap_rule.dtls_inner_if_num; - capwapmsg_inner.msg.dtls.mtu_adjust = 0; - - capwapmsg_outer.msg.dtls.enable = 0; + ip_if_num = nss_capwap_ifnum_with_core_id(t->if_num); + capwapmsg.msg.dtls.enable = 0; + capwapmsg.msg.dtls.dtls_inner_if_num = t->capwap_rule.dtls_inner_if_num; + capwapmsg.msg.dtls.mtu_adjust = 0; /* * Unconfigure trustsec tx first @@ -2060,7 +1984,6 @@ nss_capwapmgr_status_t nss_capwapmgr_con nss_status = nss_trustsec_tx_unconfigure_sgt(t->capwap_rule.dtls_inner_if_num, t->capwap_rule.outer_sgt_value); if (nss_status != NSS_TX_SUCCESS) { nss_capwapmgr_warn("%px: unconfigure trustsec_tx failed\n", dev); - dev_put(dev); return NSS_CAPWAPMGR_FAILURE_UNCONFIGURE_TRUSTSEC_TX; } } @@ -2075,7 +1998,6 @@ nss_capwapmgr_status_t nss_capwapmgr_con */ if (!in_data) { nss_capwapmgr_info("%px: dtls in_data required to create dtls tunnel\n", dev); - dev_put(dev); return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } @@ -2085,12 +2007,11 @@ nss_capwapmgr_status_t nss_capwapmgr_con * ensure that the user does not configure this mode accidentally. */ in_data->flags &= ~NSS_DTLSMGR_ENCAP_METADATA; - in_data->decap.nexthop_ifnum = nss_capwap_ifnum_with_core_id(t->if_num_outer); + in_data->decap.nexthop_ifnum = nss_capwap_ifnum_with_core_id(t->if_num); t->dtls_dev = nss_dtlsmgr_session_create(in_data); if (!t->dtls_dev) { nss_capwapmgr_warn("%px: cannot create DTLS session\n", dev); - dev_put(dev); return NSS_CAPWAPMGR_FAILURE_DI_ALLOC_FAILED; } @@ -2104,20 +2025,17 @@ nss_capwapmgr_status_t nss_capwapmgr_con ip_if_num = nss_dtlsmgr_get_interface(t->dtls_dev, NSS_DTLSMGR_INTERFACE_TYPE_OUTER); - capwapmsg_inner.msg.dtls.enable = 1; - capwapmsg_inner.msg.dtls.dtls_inner_if_num = t->capwap_rule.dtls_inner_if_num; - capwapmsg_inner.msg.dtls.mtu_adjust = t->capwap_rule.mtu_adjust; - - capwapmsg_outer.msg.dtls.enable = 1; + capwapmsg.msg.dtls.enable = 1; + capwapmsg.msg.dtls.dtls_inner_if_num = t->capwap_rule.dtls_inner_if_num; + capwapmsg.msg.dtls.mtu_adjust = t->capwap_rule.mtu_adjust; /* * Unconfigure trustsec tx first */ if (outer_trustsec_enabled) { - nss_status = nss_trustsec_tx_unconfigure_sgt(t->if_num_outer, t->capwap_rule.outer_sgt_value); + nss_status = nss_trustsec_tx_unconfigure_sgt(t->if_num, t->capwap_rule.outer_sgt_value); if (nss_status != NSS_TX_SUCCESS) { nss_capwapmgr_warn("%px: unconfigure trustsec_tx failed\n", dev); - dev_put(dev); return NSS_CAPWAPMGR_FAILURE_UNCONFIGURE_TRUSTSEC_TX; } } @@ -2130,11 +2048,11 @@ nss_capwapmgr_status_t nss_capwapmgr_con nss_status = nss_trustsec_tx_configure_sgt(ip_if_num, t->capwap_rule.gmac_ifnum, t->capwap_rule.outer_sgt_value); if (nss_status != NSS_TX_SUCCESS) { nss_capwapmgr_warn("%px: configure trustsec_tx failed\n", dev); - dev_put(dev); return NSS_CAPWAPMGR_FAILURE_CONFIGURE_TRUSTSEC_TX; } } + dev_hold(dev); priv = netdev_priv(dev); /* @@ -2200,18 +2118,11 @@ nss_capwapmgr_status_t nss_capwapmgr_con * Now configure capwap dtls */ t->tunnel_state |= NSS_CAPWAPMGR_TUNNEL_STATE_IPRULE_CONFIGURED; - status = nss_capwapmgr_tx_msg_sync(priv->nss_ctx, dev, &capwapmsg_inner); - if (status != NSS_CAPWAPMGR_SUCCESS) { - nss_capwapmgr_warn("%px: configure DTLS failed for inner node: %d\n", dev, status); - dev_put(dev); - return status; - } - - status = nss_capwapmgr_tx_msg_sync(priv->nss_ctx, dev, &capwapmsg_outer); + status = nss_capwapmgr_tx_msg_sync(priv->nss_ctx, dev, &capwapmsg); if (status != NSS_CAPWAPMGR_SUCCESS) { - nss_capwapmgr_warn("%px: configure DTLS failed for outer node: %d\n", dev, status); + nss_capwapmgr_warn("%px: configure DTLS failed : %d\n", dev, status); dev_put(dev); - return status; + return nss_status; } if (enable_dtls) { @@ -2227,8 +2138,6 @@ EXPORT_SYMBOL(nss_capwapmgr_configure_dt /* * nss_capwapmgr_verify_dtls_rekey_param() * Validate the rekey param for a DTLS tunnel and return the DTLS netdevice - * - * The caller should hold the reference on the net device before calling. */ static inline struct net_device *nss_capwapmgr_verify_dtls_rekey_param(struct net_device *dev, uint8_t tunnel_id, struct nss_dtlsmgr_config_update *udata) @@ -2261,27 +2170,16 @@ static inline struct net_device *nss_cap nss_capwapmgr_status_t nss_capwapmgr_dtls_rekey_rx_cipher_update(struct net_device *dev, uint8_t tunnel_id, struct nss_dtlsmgr_config_update *udata) { - struct net_device *dtls_ndev; - - dev_hold(dev); - dtls_ndev = nss_capwapmgr_verify_dtls_rekey_param(dev, tunnel_id, udata); - dev_put(dev); - - if (!dtls_ndev) { - goto fail; - } + struct net_device *dtls_ndev = nss_capwapmgr_verify_dtls_rekey_param(dev, tunnel_id, udata); /* * Calling dtlsmgr for rekey */ if (nss_dtlsmgr_session_update_decap(dtls_ndev, udata) != NSS_DTLSMGR_OK) { - goto fail; + nss_capwapmgr_warn("%px: tunnel: %d rekey rx cipher update failed\n", dtls_ndev, tunnel_id); + return NSS_CAPWAPMGR_FAILURE_INVALID_DTLS_CFG; } return NSS_CAPWAPMGR_SUCCESS; - -fail: - nss_capwapmgr_warn("%px: tunnel: %d rekey rx cipher update failed\n", dtls_ndev, tunnel_id); - return NSS_CAPWAPMGR_FAILURE_INVALID_DTLS_CFG; } EXPORT_SYMBOL(nss_capwapmgr_dtls_rekey_rx_cipher_update); @@ -2292,27 +2190,16 @@ EXPORT_SYMBOL(nss_capwapmgr_dtls_rekey_r nss_capwapmgr_status_t nss_capwapmgr_dtls_rekey_tx_cipher_update(struct net_device *dev, uint8_t tunnel_id, struct nss_dtlsmgr_config_update *udata) { - struct net_device *dtls_ndev; - - dev_hold(dev); - dtls_ndev = nss_capwapmgr_verify_dtls_rekey_param(dev, tunnel_id, udata); - dev_put(dev); - - if (!dtls_ndev) { - goto fail; - } + struct net_device *dtls_ndev = nss_capwapmgr_verify_dtls_rekey_param(dev, tunnel_id, udata); /* * Calling dtlsmgr for rekey */ if (nss_dtlsmgr_session_update_encap(dtls_ndev, udata) != NSS_DTLSMGR_OK) { - goto fail; + nss_capwapmgr_warn("%px: tunnel: %d rekey tx cipher update failed\n", dtls_ndev, tunnel_id); + return NSS_CAPWAPMGR_FAILURE_INVALID_DTLS_CFG; } return NSS_CAPWAPMGR_SUCCESS; - -fail: - nss_capwapmgr_warn("%px: tunnel: %d rekey rx cipher update failed\n", dtls_ndev, tunnel_id); - return NSS_CAPWAPMGR_FAILURE_INVALID_DTLS_CFG; } EXPORT_SYMBOL(nss_capwapmgr_dtls_rekey_tx_cipher_update); @@ -2323,20 +2210,16 @@ EXPORT_SYMBOL(nss_capwapmgr_dtls_rekey_t nss_capwapmgr_status_t nss_capwapmgr_dtls_rekey_rx_cipher_switch(struct net_device *dev, uint8_t tunnel_id) { struct nss_capwapmgr_tunnel *t; - nss_capwapmgr_status_t status = NSS_CAPWAPMGR_SUCCESS; - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: can't find tunnel: %d\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } if (!(t->capwap_rule.enabled_features & NSS_CAPWAPMGR_FEATURE_DTLS_ENABLED)) { nss_capwapmgr_warn("%px: tunnel does not enable DTLS: %d\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } /* @@ -2344,12 +2227,10 @@ nss_capwapmgr_status_t nss_capwapmgr_dtl */ if (!nss_dtlsmgr_session_switch_decap(t->dtls_dev)) { nss_capwapmgr_warn("%px: tunnel: %d rekey rx cipher switch failed\n", t->dtls_dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_INVALID_DTLS_CFG; + return NSS_CAPWAPMGR_FAILURE_INVALID_DTLS_CFG; } -done: - dev_put(dev); - return status; + return NSS_CAPWAPMGR_SUCCESS; } EXPORT_SYMBOL(nss_capwapmgr_dtls_rekey_rx_cipher_switch); @@ -2360,20 +2241,16 @@ EXPORT_SYMBOL(nss_capwapmgr_dtls_rekey_r nss_capwapmgr_status_t nss_capwapmgr_dtls_rekey_tx_cipher_switch(struct net_device *dev, uint8_t tunnel_id) { struct nss_capwapmgr_tunnel *t; - nss_capwapmgr_status_t status = NSS_CAPWAPMGR_SUCCESS; - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: can't find tunnel: %d\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } if (!(t->capwap_rule.enabled_features & NSS_CAPWAPMGR_FEATURE_DTLS_ENABLED)) { nss_capwapmgr_warn("%px: tunnel does not enable DTLS: %d\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } /* @@ -2381,12 +2258,10 @@ nss_capwapmgr_status_t nss_capwapmgr_dtl */ if (!nss_dtlsmgr_session_switch_encap(t->dtls_dev)) { nss_capwapmgr_warn("%px: tunnel: %d rekey tx cipher switch failed\n", t->dtls_dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_INVALID_DTLS_CFG; + return NSS_CAPWAPMGR_FAILURE_INVALID_DTLS_CFG; } -done: - dev_put(dev); - return status; + return NSS_CAPWAPMGR_SUCCESS; } EXPORT_SYMBOL(nss_capwapmgr_dtls_rekey_tx_cipher_switch); @@ -2400,22 +2275,20 @@ nss_capwapmgr_status_t nss_capwapmgr_cha struct nss_capwapmgr_priv *priv; struct nss_capwap_msg capwapmsg; struct nss_capwapmgr_tunnel *t; - nss_capwapmgr_status_t status = NSS_CAPWAPMGR_SUCCESS; + nss_capwapmgr_status_t status; - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: can't find tunnel: %d\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } if (ver > NSS_CAPWAP_VERSION_V2) { nss_capwapmgr_warn("%px: un-supported Version: %d\n", dev, ver); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } + dev_hold(dev); priv = netdev_priv(dev); /* @@ -2426,21 +2299,50 @@ nss_capwapmgr_status_t nss_capwapmgr_cha /* * Send CAPWAP data tunnel command to NSS */ - nss_capwap_msg_init(&capwapmsg, t->if_num_inner, NSS_CAPWAP_MSG_TYPE_VERSION, + nss_capwap_msg_init(&capwapmsg, t->if_num, NSS_CAPWAP_MSG_TYPE_VERSION, sizeof(struct nss_capwap_version_msg), nss_capwapmgr_msg_event_receive, dev); capwapmsg.msg.version.version = ver; status = nss_capwapmgr_tx_msg_sync(priv->nss_ctx, dev, &capwapmsg); if (status != NSS_CAPWAPMGR_SUCCESS) { nss_capwapmgr_warn("%px: Update Path MTU Tunnel error : %d \n", dev, status); + dev_put(dev); + return status; } -done: dev_put(dev); return status; } EXPORT_SYMBOL(nss_capwapmgr_change_version); /* + * nss_capwapmgr_tunnel_action() + * Common function for CAPWAP tunnel operation messages without + * any message data structures. + */ +static nss_tx_status_t nss_capwapmgr_tunnel_action(struct nss_ctx_instance *ctx, struct net_device *dev, uint32_t if_num, nss_capwap_msg_type_t cmd) +{ + struct nss_capwap_msg capwapmsg; + nss_tx_status_t status; + + /* + * Prepare the tunnel configuration parameter to send to NSS FW + */ + memset(&capwapmsg, 0, sizeof(struct nss_capwap_msg)); + + /* + * Send CAPWAP data tunnel command to NSS + */ + nss_capwap_msg_init(&capwapmsg, if_num, cmd, 0, nss_capwapmgr_msg_event_receive, dev); + status = nss_capwapmgr_tx_msg_sync(ctx, dev, &capwapmsg); + if (status != NSS_TX_SUCCESS) { + nss_capwapmgr_warn("%px: ctx: CMD: %d Tunnel error : %d \n", ctx, cmd, status); + return status; + } + + return status; +} + +/* * nss_capwapmgr_enable_tunnel() * API for enabling a data tunnel */ @@ -2448,41 +2350,28 @@ nss_capwapmgr_status_t nss_capwapmgr_ena { struct nss_capwapmgr_priv *priv; struct nss_capwapmgr_tunnel *t; - nss_capwapmgr_status_t status = NSS_CAPWAPMGR_SUCCESS; + nss_tx_status_t ret; - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: can't find tunnel: %d\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } if (t->tunnel_state & NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED) { nss_capwapmgr_warn("%px: tunnel %d is already enabled\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_TUNNEL_ENABLED; - goto done; + return NSS_CAPWAPMGR_FAILURE_TUNNEL_ENABLED; } + dev_hold(dev); priv = netdev_priv(dev); - nss_capwapmgr_info("%px: Inner:%d Outer:%d. Tunnel enable is being called\n", dev, t->if_num_inner, t->if_num_outer); - - status = nss_capwapmgr_tx_msg_enable_tunnel(priv->nss_ctx, dev, t->if_num_inner,t->if_num_outer); - if (status != NSS_CAPWAPMGR_SUCCESS) { - goto done; + nss_capwapmgr_info("%px: %d: tunnel enable is being called\n", dev, t->if_num); + ret = nss_capwapmgr_tunnel_action(priv->nss_ctx, dev, t->if_num, NSS_CAPWAP_MSG_TYPE_ENABLE_TUNNEL); + if (ret == NSS_TX_SUCCESS) { + t->tunnel_state |= NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED; } - - status = nss_capwapmgr_tx_msg_enable_tunnel(priv->nss_ctx, dev, t->if_num_outer,t->if_num_inner); - if(status != NSS_CAPWAPMGR_SUCCESS) { - nss_capwapmgr_tunnel_action(priv->nss_ctx, dev, t->if_num_inner,NSS_CAPWAP_MSG_TYPE_DISABLE_TUNNEL); - goto done; - } - - t->tunnel_state |= NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED; - -done: dev_put(dev); - return status; + return ret; } EXPORT_SYMBOL(nss_capwapmgr_enable_tunnel); @@ -2494,44 +2383,28 @@ nss_capwapmgr_status_t nss_capwapmgr_dis { struct nss_capwapmgr_priv *priv; struct nss_capwapmgr_tunnel *t; - nss_capwapmgr_status_t status = NSS_CAPWAPMGR_SUCCESS; + nss_tx_status_t ret; - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: can't find tunnel: %d\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } if (!(t->tunnel_state & NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED)) { - nss_capwapmgr_warn("%px: tunnel %d is already disabled\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_TUNNEL_DISABLED; - goto done; + nss_capwapmgr_warn("%px: tunnel %d is already enabled\n", dev, tunnel_id); + return NSS_CAPWAPMGR_FAILURE_TUNNEL_DISABLED; } + dev_hold(dev); priv = netdev_priv(dev); - nss_capwapmgr_info("%px: Inner:%d Outer:%d. Tunnel disable is being called\n", dev, t->if_num_inner, t->if_num_outer); - - status = nss_capwapmgr_tunnel_action(priv->nss_ctx, dev, t->if_num_inner,NSS_CAPWAP_MSG_TYPE_DISABLE_TUNNEL); - if (status != NSS_CAPWAPMGR_SUCCESS) { - status = NSS_CAPWAPMGR_FAILURE_TUNNEL_DISABLED; - nss_capwapmgr_warn("%px: tunnel %d disable failed\n", dev, tunnel_id); - goto done; - } - - status = nss_capwapmgr_tunnel_action(priv->nss_ctx, dev, t->if_num_outer,NSS_CAPWAP_MSG_TYPE_DISABLE_TUNNEL); - if (status != NSS_CAPWAPMGR_SUCCESS) { - nss_capwapmgr_warn("%px: tunnel %d disable failed\n", dev, tunnel_id); - nss_capwapmgr_tx_msg_enable_tunnel(priv->nss_ctx, dev, t->if_num_inner, t->if_num_outer); - goto done; + nss_capwapmgr_info("%px: %d: tunnel disable is being called\n", dev, t->if_num); + ret = nss_capwapmgr_tunnel_action(priv->nss_ctx, dev, t->if_num, NSS_CAPWAP_MSG_TYPE_DISABLE_TUNNEL); + if (ret == NSS_TX_SUCCESS) { + t->tunnel_state &= ~NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED; } - - t->tunnel_state &= ~NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED; - -done: dev_put(dev); - return status; + return ret; } EXPORT_SYMBOL(nss_capwapmgr_disable_tunnel); @@ -2545,7 +2418,7 @@ static nss_capwapmgr_status_t nss_capwap struct nss_capwapmgr_priv *priv; struct nss_capwapmgr_tunnel *t; nss_capwapmgr_status_t status = NSS_CAPWAPMGR_SUCCESS; - int32_t capwap_if_num_inner, capwap_if_num_outer, forward_if_num; + int32_t capwap_if_num, forward_if_num; uint16_t type_flags = 0; nss_tx_status_t nss_status = NSS_TX_SUCCESS; uint32_t dtls_enabled = capwap_rule->enabled_features & NSS_CAPWAPMGR_FEATURE_DTLS_ENABLED; @@ -2578,44 +2451,28 @@ static nss_capwapmgr_status_t nss_capwap return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (t) { nss_capwapmgr_warn("%px: tunnel: %d already created\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_TUNNEL_EXISTS; - goto done; + return NSS_CAPWAPMGR_FAILURE_TUNNEL_EXISTS; } - capwap_if_num_inner = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP_HOST_INNER); - if (capwap_if_num_inner < 0) { - nss_capwapmgr_warn("%px: di returned error : %d\n", dev, capwap_if_num_inner); - status = NSS_CAPWAPMGR_FAILURE_DI_ALLOC_FAILED; - goto done; + capwap_if_num = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP); + if (capwap_if_num < 0) { + nss_capwapmgr_warn("%px: di returned error : %d\n", dev, capwap_if_num); + return NSS_CAPWAPMGR_FAILURE_DI_ALLOC_FAILED; } - if (nss_capwapmgr_register_with_nss(capwap_if_num_inner, dev) != NSS_CAPWAPMGR_SUCCESS) { - nss_capwapmgr_warn("%d: NSS CAPWAP register with NSS failed", capwap_if_num_inner); - status = NSS_CAPWAPMGR_FAILURE_REGISTER_NSS; - goto fail1; - } - - capwap_if_num_outer = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP_OUTER); - if (capwap_if_num_outer < 0) { - nss_capwapmgr_warn("%px: di returned error : %d\n", dev, capwap_if_num_outer); - status = NSS_CAPWAPMGR_FAILURE_DI_ALLOC_FAILED; - goto fail2; - } - - if (nss_capwapmgr_register_with_nss(capwap_if_num_outer, dev) != NSS_CAPWAPMGR_SUCCESS) { - nss_capwapmgr_warn("%d: NSS CAPWAP register with NSS failed", capwap_if_num_outer); - status = NSS_CAPWAPMGR_FAILURE_REGISTER_NSS; - goto fail3; + if (nss_capwapmgr_register_with_nss(capwap_if_num, dev) != NSS_CAPWAPMGR_SUCCESS) { + nss_capwapmgr_warn("%d: NSS CAPWAP register with NSS failed", capwap_if_num); + (void)nss_dynamic_interface_dealloc_node(capwap_if_num, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP); + return NSS_CAPWAPMGR_FAILURE_REGISTER_NSS; } if (!dtls_enabled) { capwap_rule->mtu_adjust = 0; capwap_rule->dtls_inner_if_num = 0; - forward_if_num = nss_capwap_ifnum_with_core_id(capwap_if_num_outer); + forward_if_num = nss_capwap_ifnum_with_core_id(capwap_if_num); } else { /* * We only support the METADATA mode for pure DTLS tunnels; in CAPWAP-DTLS @@ -2623,13 +2480,14 @@ static nss_capwapmgr_status_t nss_capwap * ensure that the user does not configure this mode accidentally. */ in_data->flags &= ~NSS_DTLSMGR_ENCAP_METADATA; - in_data->decap.nexthop_ifnum = nss_capwap_ifnum_with_core_id(capwap_if_num_outer); + in_data->decap.nexthop_ifnum = nss_capwap_ifnum_with_core_id(capwap_if_num); t->dtls_dev = nss_dtlsmgr_session_create(in_data); if (!t->dtls_dev) { nss_capwapmgr_warn("%px: NSS DTLS node alloc failed\n", dev); - status = NSS_CAPWAPMGR_FAILURE_DI_ALLOC_FAILED; - goto fail4; + nss_capwapmgr_unregister_with_nss(capwap_if_num); + (void)nss_dynamic_interface_dealloc_node(capwap_if_num, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP); + return NSS_CAPWAPMGR_FAILURE_DI_ALLOC_FAILED; } capwap_rule->dtls_inner_if_num = nss_dtlsmgr_get_interface(t->dtls_dev, NSS_DTLSMGR_INTERFACE_TYPE_INNER); forward_if_num = nss_dtlsmgr_get_interface(t->dtls_dev, NSS_DTLSMGR_INTERFACE_TYPE_OUTER); @@ -2650,7 +2508,7 @@ static nss_capwapmgr_status_t nss_capwap if (nss_status != NSS_TX_SUCCESS) { nss_capwapmgr_warn("%px: configure trustsectx node failed\n", dev); status = NSS_CAPWAPMGR_FAILURE_CONFIGURE_TRUSTSEC_TX; - goto fail5; + goto fail; } } @@ -2706,20 +2564,12 @@ static nss_capwapmgr_status_t nss_capwap capwap_rule->encap.dest_ip.ip.ipv6[3] = htonl(v6->src_ip[3]); } - status = nss_capwapmgr_create_capwap_rule(dev, capwap_if_num_inner, capwap_rule, type_flags); - nss_capwapmgr_info("%px: dynamic interface if_num is :%d and capwap tunnel status:%d\n", dev, capwap_if_num_inner, status); + status = nss_capwapmgr_create_capwap_rule(dev, capwap_if_num, capwap_rule, type_flags); + nss_capwapmgr_info("%px: dynamic interface if_num is :%d and capwap tunnel status:%d\n", dev, capwap_if_num, status); if (status != NSS_CAPWAPMGR_SUCCESS) { - nss_capwapmgr_warn("%px: %d: CAPWAP rule create failed with status: %d", dev, capwap_if_num_inner, status); + nss_capwapmgr_warn("%px: %d: CAPWAP rule create failed with status: %d", dev, capwap_if_num, status); status = NSS_CAPWAPMGR_FAILURE_CAPWAP_RULE; - goto fail5; - } - - status = nss_capwapmgr_create_capwap_rule(dev, capwap_if_num_outer, capwap_rule, type_flags); - nss_capwapmgr_info("%px: dynamic interface if_num is :%d and capwap tunnel status:%d\n", dev, capwap_if_num_outer, status); - if (status != NSS_CAPWAPMGR_SUCCESS) { - nss_capwapmgr_warn("%px: %d: CAPWAP rule create failed with status: %d", dev, capwap_if_num_outer, status); - status = NSS_CAPWAPMGR_FAILURE_CAPWAP_RULE; - goto fail5; + goto fail; } if (v4) { @@ -2733,12 +2583,13 @@ static nss_capwapmgr_status_t nss_capwap if (nss_status != NSS_TX_SUCCESS) { nss_capwapmgr_warn("%px: %d: IPv4/IPv6 rule create failed with status: %d", dev, forward_if_num, nss_status); status = NSS_CAPWAPMGR_FAILURE_IP_RULE; - goto fail5; + goto fail; } + dev_hold(dev); priv = netdev_priv(dev); t = &priv->tunnel[tunnel_id]; - nss_capwapmgr_info("%px: %d: %d: CAPWAP TUNNEL CREATE DONE tunnel_id:%d (%px)\n", dev, capwap_if_num_inner, capwap_if_num_outer, tunnel_id, t); + nss_capwapmgr_info("%px: %d: CAPWAP TUNNEL CREATE DONE tunnel_id:%d (%px)\n", dev, capwap_if_num, tunnel_id, t); /* * Keep a copy of rule information. @@ -2754,33 +2605,22 @@ static nss_capwapmgr_status_t nss_capwap /* * Make it globally visible inside the netdev. */ - t->if_num_inner = capwap_if_num_inner; - t->if_num_outer = capwap_if_num_outer; - priv->if_num_to_tunnel_id[capwap_if_num_inner] = tunnel_id; - priv->if_num_to_tunnel_id[capwap_if_num_outer] = tunnel_id; + t->if_num = capwap_if_num; + priv->if_num_to_tunnel_id[capwap_if_num] = tunnel_id; t->tunnel_state |= NSS_CAPWAPMGR_TUNNEL_STATE_CONFIGURED; t->tunnel_state |= NSS_CAPWAPMGR_TUNNEL_STATE_IPRULE_CONFIGURED; - t->type_flags = type_flags; - goto done; + dev_put(dev); + return status; -fail5: +fail: + nss_capwapmgr_unregister_with_nss(capwap_if_num); + (void)nss_dynamic_interface_dealloc_node(capwap_if_num, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP); if (dtls_enabled) { if (nss_dtlsmgr_session_destroy(t->dtls_dev) != NSS_DTLSMGR_OK) { nss_capwapmgr_warn("%px: failed to destroy DTLS session", t->dtls_dev); } } -fail4: - nss_capwapmgr_unregister_with_nss(capwap_if_num_outer); -fail3: - (void)nss_dynamic_interface_dealloc_node(capwap_if_num_outer, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP_OUTER); -fail2: - nss_capwapmgr_unregister_with_nss(capwap_if_num_inner); -fail1: - (void)nss_dynamic_interface_dealloc_node(capwap_if_num_inner, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP_HOST_INNER); - -done: - dev_put(dev); return status; } @@ -2819,7 +2659,7 @@ static void nss_capwapmgr_tunnel_save_st save->rx_dup_frag += fstats->rx_dup_frag; save->rx_oversize_drops += fstats->rx_oversize_drops; save->rx_frag_timeout_drops += fstats->rx_frag_timeout_drops; - save->rx_n2h_drops += fstats->rx_n2h_drops; + save->rx_queue_full_drops += fstats->rx_queue_full_drops; save->rx_n2h_queue_full_drops += fstats->rx_n2h_queue_full_drops; save->rx_mem_failure_drops += fstats->rx_mem_failure_drops; save->rx_csum_drops += fstats->rx_csum_drops; @@ -2857,21 +2697,18 @@ nss_capwapmgr_status_t nss_capwapmgr_tun struct nss_capwapmgr_priv *priv; struct nss_capwapmgr_tunnel *t; nss_tx_status_t nss_status = NSS_TX_SUCCESS; - uint32_t if_num_inner, if_num_outer; + uint32_t if_num; nss_capwapmgr_status_t status = NSS_CAPWAPMGR_SUCCESS; - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: tunnel %d: wrong argument for tunnel destroy\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } if (!(t->tunnel_state & NSS_CAPWAPMGR_TUNNEL_STATE_CONFIGURED)) { nss_capwapmgr_warn("%px: tunnel %d is not configured yet\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_TUNNEL_NOT_CFG; - goto done; + return NSS_CAPWAPMGR_FAILURE_TUNNEL_NOT_CFG; } /* @@ -2879,49 +2716,34 @@ nss_capwapmgr_status_t nss_capwapmgr_tun */ if (t->tunnel_state & NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED) { nss_capwapmgr_warn("%px: no destroy alloed for an eanbled tunnel: %d\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_TUNNEL_ENABLED; - goto done; + return NSS_CAPWAPMGR_FAILURE_TUNNEL_ENABLED; } if (!(t->capwap_rule.l3_proto == NSS_CAPWAP_TUNNEL_IPV4 || t->capwap_rule.l3_proto == NSS_CAPWAP_TUNNEL_IPV6)) { nss_capwapmgr_warn("%px: tunnel %d: wrong argument for l3_proto\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } if (!(t->capwap_rule.which_udp == NSS_CAPWAP_TUNNEL_UDP || t->capwap_rule.which_udp == NSS_CAPWAP_TUNNEL_UDPLite)) { nss_capwapmgr_warn("%px: tunnel %d: wrong argument for which_udp(%d)\n", dev, tunnel_id, t->capwap_rule.which_udp); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } + dev_hold(dev); priv = netdev_priv(dev); - nss_capwapmgr_info("%px: %d: tunnel destroy is being called\n", dev, tunnel_id); - - if_num_inner = t->if_num_inner; - if_num_outer = t->if_num_outer; + nss_capwapmgr_info("%px: %d: tunnel destroy is being called\n", dev, t->if_num); + if_num = t->if_num; - if (priv->if_num_to_tunnel_id[if_num_inner] != tunnel_id) { + if (priv->if_num_to_tunnel_id[if_num] != tunnel_id) { nss_capwapmgr_warn("%px: %d: tunnel_id %d didn't match with tunnel_id :%d\n", - dev, if_num_inner, tunnel_id, priv->if_num_to_tunnel_id[if_num_inner]); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; - } - - if (priv->if_num_to_tunnel_id[if_num_outer] != tunnel_id) { - nss_capwapmgr_warn("%px: %d: tunnel_id %d didn't match with tunnel_id :%d\n", - dev, if_num_outer, tunnel_id, priv->if_num_to_tunnel_id[if_num_outer]); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; - } - - if (nss_capwap_get_stats(if_num_inner, &stats) == true) { - nss_capwapmgr_tunnel_save_stats(&global.tunneld, &stats); + dev, if_num, tunnel_id, priv->if_num_to_tunnel_id[if_num]); + dev_put(dev); + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } - if (nss_capwap_get_stats(if_num_outer, &stats) == true) { + if (nss_capwap_get_stats(if_num, &stats) == true) { nss_capwapmgr_tunnel_save_stats(&global.tunneld, &stats); } @@ -2961,10 +2783,9 @@ nss_capwapmgr_status_t nss_capwapmgr_tun } if (nss_status != NSS_TX_SUCCESS) { - nss_capwapmgr_warn("%px: Unconfigure IP rule failed for tunnel : %d\n", - dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_IP_DESTROY_RULE; - goto done; + nss_capwapmgr_warn("%px: %d: Unconfigure IP rule failed for tunnel : %d\n", + dev, if_num, tunnel_id); + return NSS_CAPWAPMGR_FAILURE_IP_DESTROY_RULE; } t->tunnel_state &= ~NSS_CAPWAPMGR_TUNNEL_STATE_IPRULE_CONFIGURED; } @@ -2972,45 +2793,36 @@ nss_capwapmgr_status_t nss_capwapmgr_tun /* * Destroy CAPWAP rule now. */ - status = nss_capwapmgr_tunnel_action(priv->nss_ctx, dev, if_num_outer, NSS_CAPWAP_MSG_TYPE_UNCFG_RULE); + status = nss_capwapmgr_tunnel_action(priv->nss_ctx, dev, if_num, NSS_CAPWAP_MSG_TYPE_UNCFG_RULE); if (status != NSS_CAPWAPMGR_SUCCESS) { nss_capwapmgr_warn("%px: %d: Unconfigure CAPWAP rule failed for tunnel : %d\n", - dev, if_num_outer, tunnel_id); - goto fail; - - } + dev, if_num, tunnel_id); - status = nss_capwapmgr_tunnel_action(priv->nss_ctx, dev, if_num_inner, NSS_CAPWAP_MSG_TYPE_UNCFG_RULE); - if (status != NSS_CAPWAPMGR_SUCCESS) { - nss_capwapmgr_warn("%px: %d: Unconfigure CAPWAP rule failed for tunnel : %d\n", - dev, if_num_inner, tunnel_id); - status = nss_capwapmgr_create_capwap_rule(dev, if_num_outer, &(t->capwap_rule), t->type_flags); - if (status != NSS_CAPWAPMGR_SUCCESS) { - nss_capwapmgr_warn("%px: %d: re creating the CAPWAP rule failed for tunnel : %d\n", - dev, if_num_inner, tunnel_id); - goto done; + if (t->capwap_rule.l3_proto == NSS_CAPWAP_TUNNEL_IPV4) { + nss_status = nss_capwapmgr_configure_ipv4(&t->ip_rule.v4, 0, 0); + if (nss_status == NSS_TX_SUCCESS) { + t->tunnel_state |= NSS_CAPWAPMGR_TUNNEL_STATE_IPRULE_CONFIGURED; } - goto fail; + } else { + nss_status = nss_capwapmgr_configure_ipv6(&t->ip_rule.v6, 0, 0); + if (nss_status == NSS_TX_SUCCESS) { + t->tunnel_state |= NSS_CAPWAPMGR_TUNNEL_STATE_IPRULE_CONFIGURED; + } + } + return NSS_CAPWAPMGR_FAILURE_CAPWAP_DESTROY_RULE; } - nss_capwapmgr_unregister_with_nss(if_num_outer); - nss_capwapmgr_unregister_with_nss(if_num_inner); + nss_capwapmgr_unregister_with_nss(if_num); /* * Deallocate dynamic interface */ - nss_status = nss_dynamic_interface_dealloc_node(if_num_outer, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP_OUTER); - if (nss_status != NSS_TX_SUCCESS) { - nss_capwapmgr_warn("%px: %d: Dealloc of dynamic interface failed for tunnel : %d\n", - dev, if_num_outer, tunnel_id); - } - - nss_status = nss_dynamic_interface_dealloc_node(if_num_inner, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP_HOST_INNER); + nss_status = nss_dynamic_interface_dealloc_node(if_num, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP); if (nss_status != NSS_TX_SUCCESS) { nss_capwapmgr_warn("%px: %d: Dealloc of dynamic interface failed for tunnel : %d\n", - dev, if_num_inner, tunnel_id); + dev, if_num, tunnel_id); } /* @@ -3020,9 +2832,8 @@ nss_capwapmgr_status_t nss_capwapmgr_tun if (t->capwap_rule.enabled_features & NSS_CAPWAPMGR_FEATURE_DTLS_ENABLED) { nss_status = nss_trustsec_tx_unconfigure_sgt(t->capwap_rule.dtls_inner_if_num, t->capwap_rule.outer_sgt_value); } else { - nss_status = nss_trustsec_tx_unconfigure_sgt(t->if_num_outer, t->capwap_rule.outer_sgt_value); + nss_status = nss_trustsec_tx_unconfigure_sgt(t->if_num, t->capwap_rule.outer_sgt_value); } - if (nss_status != NSS_TX_SUCCESS) { nss_capwapmgr_warn("%px: unconfigure trustsec_tx failed\n", dev); } @@ -3037,35 +2848,14 @@ nss_capwapmgr_status_t nss_capwapmgr_tun } } + t->if_num = 0; t->tunnel_state &= ~NSS_CAPWAPMGR_TUNNEL_STATE_CONFIGURED; - priv->if_num_to_tunnel_id[if_num_inner] = -1; - priv->if_num_to_tunnel_id[if_num_outer] = -1; - + priv->if_num_to_tunnel_id[if_num] = 0; memset(t, 0, sizeof(struct nss_capwapmgr_tunnel)); - t->if_num_inner = -1; - t->if_num_outer = -1; - - nss_capwapmgr_info("%px: Tunnel %d is completely destroyed\n", dev , tunnel_id); - status = NSS_CAPWAPMGR_SUCCESS; - goto done; - -fail: - if (t->capwap_rule.l3_proto == NSS_CAPWAP_TUNNEL_IPV4) { - nss_status = nss_capwapmgr_configure_ipv4(&t->ip_rule.v4, 0, 0); - } else { - nss_status = nss_capwapmgr_configure_ipv6(&t->ip_rule.v6, 0, 0); - } - - if (nss_status == NSS_TX_SUCCESS) { - t->tunnel_state |= NSS_CAPWAPMGR_TUNNEL_STATE_IPRULE_CONFIGURED; - } - - status = NSS_CAPWAPMGR_FAILURE_CAPWAP_DESTROY_RULE; - -done: + nss_capwapmgr_info("%px: %d: Tunnel %d is completely destroyed\n", dev, if_num, tunnel_id); dev_put(dev); - return status; + return NSS_CAPWAPMGR_SUCCESS; } EXPORT_SYMBOL(nss_capwapmgr_tunnel_destroy); @@ -3083,18 +2873,17 @@ static inline nss_capwapmgr_status_t nss struct nss_capwapmgr_tunnel *t; nss_capwapmgr_status_t status; - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_warn("%px: can't find tunnel: %d\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } + dev_hold(dev); priv = netdev_priv(dev); memset(&capwapmsg, 0, sizeof(struct nss_capwap_msg)); - nss_capwap_msg_init(&capwapmsg, t->if_num_outer, cmd, + nss_capwap_msg_init(&capwapmsg, t->if_num, cmd, sizeof(struct nss_capwap_flow_rule_msg), nss_capwapmgr_msg_event_receive, dev); /* @@ -3121,7 +2910,6 @@ static inline nss_capwapmgr_status_t nss nss_capwapmgr_warn("%px: send flow rule message failed with error: %d\n", dev, status); } -done: dev_put(dev); return status; } @@ -3160,85 +2948,29 @@ nss_capwapmgr_status_t nss_capwapmgr_tun uint8_t tunnel_id, struct nss_capwap_tunnel_stats *stats) { struct nss_capwapmgr_tunnel *t; - struct nss_capwap_tunnel_stats stats_temp; - nss_capwapmgr_status_t status = NSS_CAPWAPMGR_SUCCESS; if (!stats) { nss_capwapmgr_warn("%px: invalid rtnl structure\n", dev); return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } - dev_hold(dev); t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id); if (!t) { nss_capwapmgr_trace("%px: can't find tunnel: %d\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_BAD_PARAM; - goto done; + return NSS_CAPWAPMGR_FAILURE_BAD_PARAM; } if (!(t->tunnel_state & NSS_CAPWAPMGR_TUNNEL_STATE_CONFIGURED)) { nss_capwapmgr_trace("%px: tunnel: %d not configured yet\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_TUNNEL_NOT_CFG; - goto done; + return NSS_CAPWAPMGR_FAILURE_TUNNEL_NOT_CFG; } - /* - * Copy the inner interface stats. - */ - if (nss_capwap_get_stats(t->if_num_inner, &stats_temp) == false) { + if (nss_capwap_get_stats(t->if_num, stats) == false) { nss_capwapmgr_warn("%px: tunnel %d not ready yet\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_NOT_READY; - goto done; + return NSS_CAPWAPMGR_FAILURE_NOT_READY; } - stats->dtls_pkts += stats_temp.dtls_pkts; - stats->tx_segments += stats_temp.tx_segments; - stats->tx_queue_full_drops += stats_temp.tx_queue_full_drops; - stats->tx_mem_failure_drops += stats_temp.tx_mem_failure_drops; - stats->tx_dropped_sg_ref += stats_temp.tx_dropped_sg_ref; - stats->tx_dropped_ver_mis += stats_temp.tx_dropped_ver_mis; - stats->tx_dropped_hroom += stats_temp.tx_dropped_hroom; - stats->tx_dropped_dtls += stats_temp.tx_dropped_dtls; - stats->tx_dropped_nwireless += stats_temp.tx_dropped_nwireless; - - /* - * Pnode tx stats for Inner node. - */ - stats->pnode_stats.tx_packets += stats_temp.pnode_stats.tx_packets; - stats->pnode_stats.tx_bytes += stats_temp.pnode_stats.tx_bytes; - stats->tx_dropped_inner += stats_temp.tx_dropped_inner; - - /* - * Copy the outer interface stats. - */ - if (nss_capwap_get_stats(t->if_num_outer, &stats_temp) == false) { - nss_capwapmgr_warn("%px: tunnel %d not ready yet\n", dev, tunnel_id); - status = NSS_CAPWAPMGR_FAILURE_NOT_READY; - goto done; - } - - stats->rx_segments += stats_temp.rx_segments; - stats->dtls_pkts += stats_temp.dtls_pkts; - stats->rx_dup_frag += stats_temp.rx_dup_frag; - stats->rx_oversize_drops += stats_temp.rx_oversize_drops; - stats->rx_frag_timeout_drops += stats_temp.rx_frag_timeout_drops; - stats->rx_n2h_drops += stats_temp.rx_n2h_drops; - stats->rx_n2h_queue_full_drops += stats_temp.rx_n2h_queue_full_drops; - stats->rx_mem_failure_drops += stats_temp.rx_mem_failure_drops; - stats->rx_csum_drops += stats_temp.rx_csum_drops; - stats->rx_malformed += stats_temp.rx_malformed; - stats->rx_frag_gap_drops += stats_temp.rx_frag_gap_drops; - - /* - * Pnode rx stats for outer node. - */ - stats->pnode_stats.rx_packets += stats_temp.pnode_stats.rx_packets; - stats->pnode_stats.rx_bytes += stats_temp.pnode_stats.rx_bytes; - stats->pnode_stats.rx_dropped += stats_temp.pnode_stats.rx_dropped; - -done: - dev_put(dev); - return status; + return NSS_CAPWAPMGR_SUCCESS; } EXPORT_SYMBOL(nss_capwapmgr_tunnel_stats); @@ -3341,7 +3073,10 @@ EXPORT_SYMBOL(nss_capwapmgr_get_netdev); */ static int nss_capwapmgr_netdev_up(struct net_device *netdev) { + struct nss_capwapmgr_priv *priv; uint8_t i; + + priv = netdev_priv(netdev); for (i = 0; i < NSS_CAPWAPMGR_MAX_TUNNELS; i++) { (void)nss_capwapmgr_enable_tunnel(nss_capwapmgr_ndev, i); } @@ -3355,7 +3090,10 @@ static int nss_capwapmgr_netdev_up(struc */ static int nss_capwapmgr_netdev_down(struct net_device *netdev) { + struct nss_capwapmgr_priv *priv; uint8_t i; + + priv = netdev_priv(netdev); for (i = 0; i < NSS_CAPWAPMGR_MAX_TUNNELS; i++) { (void)nss_capwapmgr_disable_tunnel(nss_capwapmgr_ndev, i); } @@ -3367,7 +3105,7 @@ static int nss_capwapmgr_netdev_down(str * nss_capwapmgr_netdev_event() * Net device notifier for NSS CAPWAP manager module */ -static int nss_capwapmgr_netdev_event(struct notifier_block *nb, unsigned long event, void *dev) +static int nss_capwapmgr_netdev_event(struct notifier_block *nb, unsigned long event, void *dev) { struct net_device *netdev = (struct net_device *)dev; --- a/clmapmgr/nss_clmapmgr.c +++ b/clmapmgr/nss_clmapmgr.c @@ -84,17 +84,16 @@ fail: } /* - * nss_clmapmgr_get_dev_stats64() + * nss_clmapmgr_dev_stats64() * Netdev ops function to retrieve stats. */ -static struct rtnl_link_stats64 *nss_clmapmgr_get_dev_stats64(struct net_device *dev, +void nss_clmapmgr_dev_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { struct nss_clmapmgr_priv_t *priv; if (!stats) { nss_clmapmgr_warning("%px: invalid rtnl structure\n", dev); - return stats; } dev_hold(dev); @@ -109,30 +108,7 @@ static struct rtnl_link_stats64 *nss_clm memcpy(stats, &priv->stats, sizeof(struct rtnl_link_stats64)); dev_put(dev); - return stats; -} - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) -/* - * nss_clmapmgr_dev_stats64() - * Netdev ops function to retrieve stats for kernel version < 4.6 - */ -static struct rtnl_link_stats64 *nss_clmapmgr_dev_stats64(struct net_device *dev, - struct rtnl_link_stats64 *tot) -{ - return nss_clmapmgr_get_dev_stats64(dev, tot); -} -#else -/* - * nss_clmapmgr_dev_stats64() - * Netdev ops function to retrieve stats for kernel version >= 4.6 - */ -static void nss_clmapmgr_dev_stats64(struct net_device *dev, - struct rtnl_link_stats64 *tot) -{ - nss_clmapmgr_get_dev_stats64(dev, tot); } -#endif /* * nss_clmapmgr_dev_init() --- a/dtls/v1.0/nss_connmgr_dtls_netdev.c +++ b/dtls/v1.0/nss_connmgr_dtls_netdev.c @@ -160,7 +160,7 @@ static void nss_dtlsmgr_dev_setup(struct dev->ethtool_ops = NULL; dev->header_ops = NULL; dev->netdev_ops = &nss_dtlsmgr_session_ops; - dev->destructor = NULL; + dev->priv_destructor = NULL; memcpy(dev->dev_addr, "\xaa\xbb\xcc\xdd\xee\xff", dev->addr_len); memset(dev->broadcast, 0xff, dev->addr_len); --- a/dtls/v2.0/Makefile +++ b/dtls/v2.0/Makefile @@ -3,7 +3,7 @@ ccflags-y += $(NSS_CCFLAGS) -I$(obj)/../../exports ccflags-y += -DNSS_DTLSMGR_DEBUG_LEVEL=0 ccflags-y += -DNSS_DTLSMGR_BUILD_ID=\"'Build_ID - $(shell date +'%m/%d/%y, %H:%M:%S') SoC=$(SoC)'\" -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-dtlsmgr.o qca-nss-dtlsmgr-objs += nss_dtlsmgr.o --- a/dtls/v2.0/nss_dtlsmgr_ctx.c +++ b/dtls/v2.0/nss_dtlsmgr_ctx.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -627,7 +627,7 @@ struct net_device *nss_dtlsmgr_session_c * so that the skb data pointer remains 4 byte aligned when the * headroom/tailroom is adjusted. */ - dev->needed_headroom = ALIGN(ctx->encap.headroom, 4); + dev->needed_headroom = ALIGN(ctx->encap.headroom + NSS_DTLSMGR_EDMA_PRE_HDR_SZ, 4); dev->needed_tailroom = ALIGN(ctx->encap.tailroom, 4); ctx->app_data = cfg->app_data; @@ -643,7 +643,7 @@ struct net_device *nss_dtlsmgr_session_c ctx->app_data = ctx; } - error = register_netdev(dev); + error = rtnl_is_locked() ? register_netdevice(dev) : register_netdev(dev); if (error < 0) { nss_dtlsmgr_warn("%px: unable register net_device(%s)", ctx, dev->name); goto destroy_decap; @@ -708,7 +708,7 @@ nss_dtlsmgr_status_t nss_dtlsmgr_session NSS_DTLSMGR_SET_MAGIC(ctx, 0); - unregister_netdev(dev); + rtnl_is_locked() ? unregister_netdevice(dev) : unregister_netdev(dev); return NSS_DTLSMGR_OK; } --- a/dtls/v2.0/nss_dtlsmgr_ctx_dev.c +++ b/dtls/v2.0/nss_dtlsmgr_ctx_dev.c @@ -349,7 +349,7 @@ static netdev_tx_t nss_dtlsmgr_ctx_dev_t stats = &encap->stats; nhead = dev->needed_headroom; - ntail = dev->needed_tailroom + nhead; /* Firmware uses tailroom for header add */ + ntail = dev->needed_tailroom; /* * Check if skb is shared; unshare in case it is shared --- a/eogremgr/nss_eogremgr.c +++ b/eogremgr/nss_eogremgr.c @@ -19,10 +19,10 @@ * NSS EOGRE manager */ +#include #include #include #include "nss_connmgr_gre_public.h" -#include #include "nss_eogremgr.h" #include "nss_eogremgr_priv.h" @@ -565,15 +565,12 @@ static void __exit nss_eogremgr_exit_mod */ static int __init nss_eogremgr_init_module(void) { - -#ifdef CONFIG_OF /* * If the node is not compatible, don't do anything. */ if (!of_find_node_by_name(NULL, "nss-common")) { return 0; } -#endif nss_eogremgr_info("module %s loaded\n", NSS_CLIENT_BUILD_ID); --- a/exports/nss_capwapmgr.h +++ b/exports/nss_capwapmgr.h @@ -61,10 +61,8 @@ struct nss_capwapmgr_response { */ struct nss_capwapmgr_tunnel { struct net_device *dtls_dev; /**< DTLS netdevice */ - uint32_t if_num_inner; /**< Interface number of the INNER CAPWAP node */ - uint32_t if_num_outer; /**< Interface number of the OUTER CAPWAP node */ + uint32_t if_num; /**< Interface number of NSS */ uint32_t tunnel_state; /**< Tunnel state */ - uint16_t type_flags; /**< Tunnel Type to determine header size */ union { struct nss_ipv4_create v4; /**< IPv4 rule structure */ struct nss_ipv6_create v6; /**< IPv6 rule struture */ @@ -224,7 +222,7 @@ nss_capwapmgr_status_t nss_capwapmgr_upd * * @return nss_capwapmgr_status_t */ -extern nss_capwapmgr_status_t nss_capwapmgr_update_src_interface(struct net_device *dev, uint8_t tunnel_id, uint32_t src_interface_num); +extern nss_capwapmgr_status_t nss_capwapmgr_update_src_interface(struct net_device *dev, uint8_t tunnel_id, int32_t src_interface_num); /** * @brief Delete a DSCP prioritization rule that was created. --- a/exports/nss_dtlsmgr.h +++ b/exports/nss_dtlsmgr.h @@ -60,12 +60,6 @@ #define NSS_DTLSMGR_METADATA_FLAG_SEQ 0x0002 /**< Metadata has a valid sequence no. */ #define NSS_DTLSMGR_METADATA_FLAG_CTYPE 0x0004 /**< Metadata has a valid DTLS content type */ -/* - * NSS DTLS manager reserved size of header - */ -#define NSS_DTLSMGR_NEEDED_HEADROOM_SZ 128 -#define NSS_DTLSMGR_NEEDED_TAILROOM_SZ 128 - /** * NSS DTLS manager status */ @@ -134,7 +128,7 @@ enum nss_dtlsmgr_metadata_result { * NSS DTLS manager cryptographic structure to represent key and its length. */ struct nss_dtlsmgr_crypto_data { - const uint8_t *data; /**< Pointer to key or nonce. */ + uint8_t *data; /**< Pointer to key or nonce. */ uint16_t len; /**< Length of the key. */ }; --- a/exports/nss_ipsecmgr.h +++ b/exports/nss_ipsecmgr.h @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2014-2019, 2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -252,10 +252,7 @@ struct nss_ipsecmgr_sa_stats { uint32_t pkt_count; /**< Number of packets processed. */ uint32_t pkt_failed; /**< Number of packets failed in processing. */ uint16_t window_size; /**< Current size of the window. */ - uint16_t replay_fail_alarm; /**< Alarm for consecutive hash fail. */ - uint32_t fail_replay_win; /**< Failure in anti-replay; packet outside the window */ - uint32_t fail_replay_dup; /**< Failure in anti-replay; duplicate records */ - uint32_t fail_auth; /**< Failure in authenticating the data */ + bool replay_fail_alarm; /**< Alarm for consecutive hash fail. */ }; /** @@ -270,20 +267,6 @@ struct nss_ipsecmgr_event { }; /** - * nss_ipsecmgr_sa_info - * Crypto information for an already created SA. - */ -struct nss_ipsecmgr_sa_info { - uint16_t session_idx; /**< Crypto Session index */ - uint16_t hdr_len; /**< Encap header length */ - uint16_t trailer_len; /**< Encap Trailer length */ - uint8_t blk_len; /**< Cipher Block length */ - uint8_t iv_len; /**< Cipher IV lengh */ - uint8_t hash_len; /**< Hash lengh */ - uint8_t res[3]; /**< Reserved */ -}; - -/** * nss_ipsecmgr_sa_cmn_init_keys * Fill and initialize common information for SA creation with crypto keys. * @@ -392,20 +375,6 @@ static inline bool nss_ipsecmgr_sa_cmn_i return true; } -/** - * nss_ipsecmgr_sa_set_transport - * Enable transport mode for an SA thats is getting initialized. - * - * @datatypes - * nss_ipsecmgr_sa_cmn \n - * - * @param[in/out] cmn Pointer to the common IPsec manager SA configuration information. - */ -static inline void nss_ipsecmgr_sa_set_transport(struct nss_ipsecmgr_sa_cmn *cmn) -{ - cmn->transport_mode = true; -} - #ifdef __KERNEL__ /* only kernel will use. */ /** @@ -439,7 +408,6 @@ struct nss_ipsecmgr_callback { struct net_device *skb_dev; /**< Net device to use for Socket Buffer. */ nss_ipsecmgr_data_callback_t data_cb; /**< Data callback function. */ nss_ipsecmgr_event_callback_t event_cb; /**< Event callback function. */ - nss_ipsecmgr_data_callback_t except_cb; /**< Outer exception callback function. */ }; /** @@ -654,35 +622,5 @@ nss_ipsecmgr_status_t nss_ipsecmgr_sa_tx nss_ipsecmgr_status_t nss_ipsecmgr_sa_tx_outer(struct net_device *tun, struct nss_ipsecmgr_sa_tuple *sa, struct sk_buff *skb); -/* - * nss_ipsecmgr_cra_name2algo() - * Get ipsecmgr algo from cra name. - * - * @param[in] cra_name Name of the crypto algo. - * - * @return - * nss_ipsecmgr_algo - */ -enum nss_ipsecmgr_algo nss_ipsecmgr_cra_name2algo(const char *cra_name); - -/* - * nss_ipsecmgr_sa_get_info() - * Get Crypto information for an already created SA. - * - * @datatypes - * net_device \n - * nss_ipsecmgr_sa_tuple \n - * nss_ipsecmgr_sa_info - * - * @param[in] tun Pointer to the network device associated with the tunnel. - * @param[in] sa Pointer to the SA tuple for which info is to be retrieved. - * @param[out] info Pointer to the SA info to fill. - * - * @return - * Success or failure. - */ -bool nss_ipsecmgr_sa_get_info(struct net_device *tun, struct nss_ipsecmgr_sa_tuple *sa, - struct nss_ipsecmgr_sa_info *info); - #endif /* __KERNEL__ */ #endif /* __NSS_IPSECMGR_H */ --- a/exports/nss_l2tpmgr.h +++ b/exports/nss_l2tpmgr.h @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2019, 2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2019 The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -16,25 +16,22 @@ #ifndef __NSS_L2TPMGR_H__ #define __NSS_L2TPMGR_H__ -typedef int32_t (*get_ipsec_ifnum_by_dev_callback_t)(struct net_device *); -typedef int32_t (*get_ipsec_ifnum_by_ip_addr_callback_t)(uint8_t ipversion, uint32_t *src_ip, uint32_t *dest_ip); +typedef struct net_device *(*get_ipsec_tundev_callback_t)(struct net_device *dev); /** * l2tpmgr_ipsecmgr_cb - * Callback to get the dummy IPSec interface number that was used to register with NSS - * by the IPSec manager when given the IPSec Linux dev. - * get_ifnum_by_dev: passes net_device ptr to get associated IPsec if_num in KLIPS - * get_ifnum_by_ip_addr: passes IPv4 src & dest addr in Big-endian form to get IPsec if_num in XFRM + * Callback to get the dummy IPSec netdev that was + * used to register with NSS by the IPSec manager + * when given the IPSec Linux dev. */ struct l2tpmgr_ipsecmgr_cb { - get_ipsec_ifnum_by_dev_callback_t get_ifnum_by_dev; - get_ipsec_ifnum_by_ip_addr_callback_t get_ifnum_by_ip_addr; + get_ipsec_tundev_callback_t cb; + /**< IPSec mgr Callback> */ }; -#if defined(NSS_L2TP_IPSEC_BIND_BY_NETDEV) /** - * l2tpmgr_register_ipsecmgr_callback_by_netdev - * Register IPSecmgr callback function with l2tpmgr by netdev for KLIPS. + * l2tpmgr_register_ipsecmgr_callback + * Register IPSecmgr callback function with l2tpmgr. * * @datatypes * l2tpmgr_ipsecmgr_cb \n @@ -44,38 +41,15 @@ struct l2tpmgr_ipsecmgr_cb { * @return * none */ -void l2tpmgr_register_ipsecmgr_callback_by_netdev(struct l2tpmgr_ipsecmgr_cb *cb); +void l2tpmgr_register_ipsecmgr_callback(struct l2tpmgr_ipsecmgr_cb *cb); /** * l2tpmgr_unregister_ipsecmgr_callback - * Unregister IPSecmgr callback function with l2tpmgr by netdev for KLIPS. + * Unregister IPSecmgr callback function with l2tpmgr. * * @return * none */ -void l2tpmgr_unregister_ipsecmgr_callback_by_netdev(void); -#endif +void l2tpmgr_unregister_ipsecmgr_callback(void); -/** - * l2tpmgr_register_ipsecmgr_callback_by_ipaddr - * Register IPSecmgr callback function with l2tpmgr by IP address for XFRM. - * - * @datatypes - * l2tpmgr_ipsecmgr_cb \n - * - * @param[in] cb IPSecmgr callback function to be registered with l2tpmgr. - * - * @return - * none - */ -void l2tpmgr_register_ipsecmgr_callback_by_ipaddr(struct l2tpmgr_ipsecmgr_cb *cb); - -/** - * l2tpmgr_unregister_ipsecmgr_callback_by_ipaddr - * Unregister IPSecmgr callback function with l2tpmgr by IP address for XFRM. - * - * @return - * none - */ -void l2tpmgr_unregister_ipsecmgr_callback_by_ipaddr(void); #endif --- a/gre/Makefile +++ b/gre/Makefile @@ -1,7 +1,7 @@ # Makefile for gre client ccflags-y += -I$(obj)/../../exports -I$(obj)/../.. ccflags-y += -DNSS_GRE_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-gre.o qca-nss-gre-objs := nss_connmgr_gre.o nss_connmgr_gre_v4.o nss_connmgr_gre_v6.o --- a/gre/nss_connmgr_gre_v4.c +++ b/gre/nss_connmgr_gre_v4.c @@ -98,12 +98,9 @@ static int nss_connmgr_gre_v4_get_mac_ad neigh = neigh_lookup(&arp_tbl, (const void *)&raddr, rt->dst.dev); } - if (neigh) { - if (!(neigh->nud_state & NUD_VALID) || !is_valid_ether_addr(neigh->ha)) { - nss_connmgr_gre_info("neigh lookup failed for %pI4, state=%x, neigh->ha=%pM\n", &raddr, neigh->nud_state, neigh->ha); - neigh_release(neigh); - neigh = NULL; - } + if (neigh && !is_valid_ether_addr(neigh->ha)) { + neigh_release(neigh); + neigh = NULL; } /* @@ -122,13 +119,6 @@ static int nss_connmgr_gre_v4_get_mac_ad msleep(2000); } - if (!(neigh->nud_state & NUD_VALID) || !is_valid_ether_addr(neigh->ha)) { - ip_rt_put(rt); - nss_connmgr_gre_warning("invalid neigh state (%x) or invalid MAC(%pM) for %pI4\n", neigh->nud_state, neigh->ha, &raddr); - neigh_release(neigh); - return GRE_ERR_NEIGH_CREATE; - } - if (neigh->dev->type == ARPHRD_LOOPBACK) { ip_rt_put(rt); neigh_release(neigh); @@ -172,14 +162,6 @@ int nss_connmgr_gre_v4_set_config(struct } } - /* - * IP address validate - */ - if ((cfg->src_ip == 0) || (cfg->dest_ip == 0)) { - nss_connmgr_gre_warning("Source ip/Destination IP is invalid"); - return GRE_ERR_INVALID_IP; - } - memset(t, 0, sizeof(struct ip_tunnel)); priv->pad_len = (cfg->add_padding) ? GRE_HDR_PAD_LEN : 0; --- a/gre/nss_connmgr_gre_v6.c +++ b/gre/nss_connmgr_gre_v6.c @@ -95,7 +95,8 @@ static int nss_connmgr_gre_v6_get_mac_ad /* * Find src MAC address */ - local_dev = (struct net_device *)ipv6_dev_find(&init_net, &src_addr, 1); + local_dev = NULL; + local_dev = (struct net_device *)ipv6_dev_find(&init_net, &src_addr, local_dev); if (!local_dev) { nss_connmgr_gre_warning("Unable to find local dev for %pI6", src_ip); return GRE_ERR_NO_LOCAL_NETDEV; @@ -106,7 +107,6 @@ static int nss_connmgr_gre_v6_get_mac_ad /* * Find dest MAC address */ - rt = nss_connmgr_gre_v6_route_lookup(&init_net, &dst_addr); if (!rt) { nss_connmgr_gre_warning("Unable to find route lookup for %pI6", dest_ip); @@ -118,12 +118,9 @@ static int nss_connmgr_gre_v6_get_mac_ad #else neigh = rt->dst.ops->neigh_lookup(&rt->dst, NULL, &dst_addr); #endif - if (neigh) { - if (!(neigh->nud_state & NUD_VALID) || !is_valid_ether_addr(neigh->ha)) { - nss_connmgr_gre_warning("neigh state is either invalid (%x) or mac address is null (%pM) for %pI6", neigh->nud_state, neigh->ha, dest_ip); - neigh_release(neigh); - neigh = NULL; - } + if (neigh && !is_valid_ether_addr(neigh->ha)) { + neigh_release(neigh); + neigh = NULL; } if (!neigh) { @@ -143,8 +140,7 @@ static int nss_connmgr_gre_v6_get_mac_ad * Release hold on existing route entry, and find the route entry again */ ip6_rt_put(rt); - - rt = nss_connmgr_gre_v6_route_lookup(&init_net, &dst_addr); + rt = rt6_lookup(&init_net, &dst_addr, NULL, 0, NULL, 0); if (!rt) { nss_connmgr_gre_warning("Unable to find route lookup for %pI6\n", dest_ip); return GRE_ERR_NEIGH_LOOKUP; @@ -155,19 +151,11 @@ static int nss_connmgr_gre_v6_get_mac_ad #else neigh = rt->dst.ops->neigh_lookup(&rt->dst, NULL, &dst_addr); #endif - - if (!neigh) { + if (!neigh || !is_valid_ether_addr(neigh->ha)) { ip6_rt_put(rt); nss_connmgr_gre_warning("Err in MAC address, neighbour look up failed\n"); return GRE_ERR_NEIGH_LOOKUP; } - - if (!(neigh->nud_state & NUD_VALID) || !is_valid_ether_addr(neigh->ha)) { - ip6_rt_put(rt); - nss_connmgr_gre_warning("Err in MAC address, invalid neigh state (%x) or invalid mac(%pM)\n", neigh->nud_state, neigh->ha); - neigh_release(neigh); - return GRE_ERR_NEIGH_LOOKUP; - } } ether_addr_copy(dest_mac, neigh->ha); --- a/gre/test/Makefile +++ b/gre/test/Makefile @@ -1,6 +1,6 @@ # Makefile for custom gre test module ccflags-y += -I$(obj)/../../../exports -I$(obj)/../../.. -I$(obj)/../ ccflags-y += -DNSS_GRE_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-gre-test.o qca-nss-gre-test-objs := nss_connmgr_gre_test.o --- a/gre/test/nss_connmgr_gre_test.c +++ b/gre/test/nss_connmgr_gre_test.c @@ -229,10 +229,12 @@ static int nss_connmgr_gre_test_open_pro /* * Proc ops */ -static const struct file_operations nss_connmgr_gre_test_proc_ops = { - .open = nss_connmgr_gre_test_open_proc, - .write = nss_connmgr_gre_test_write_proc, - .read = seq_read, +static const struct proc_ops nss_connmgr_gre_test_proc_ops = { + .proc_open = nss_connmgr_gre_test_open_proc, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = nss_connmgr_gre_test_write_proc, }; /* --- a/ipsecmgr/v1.0/Makefile +++ b/ipsecmgr/v1.0/Makefile @@ -2,7 +2,7 @@ ccflags-y := -I$(obj) -I$(obj)/../.. ccflags-y += -DNSS_CLIENT_BUILD_ID="$(BUILD_ID)" -ccflags-y += -Wall -Werror +ccflags-y += -Werror ifeq ($(SoC), fsm9010) ccflags-y += -DNSS_IPSECMGR_PMTU_SUPPORT endif --- a/ipsecmgr/v1.0/nss_ipsecmgr.c +++ b/ipsecmgr/v1.0/nss_ipsecmgr.c @@ -377,7 +377,7 @@ free: * nss_ipsecmgr_tunnel_stats() * get tunnel statistics */ -static struct rtnl_link_stats64 *nss_ipsecmgr_tunnel_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) +void nss_ipsecmgr_tunnel_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { struct nss_ipsecmgr_priv *priv = netdev_priv(dev); @@ -389,8 +389,6 @@ static struct rtnl_link_stats64 *nss_ips read_lock_bh(&ipsecmgr_ctx->lock); memcpy(stats, &priv->stats, sizeof(struct rtnl_link_stats64)); read_unlock_bh(&ipsecmgr_ctx->lock); - - return stats; } /* @@ -442,7 +440,7 @@ static void nss_ipsecmgr_tunnel_setup(st dev->header_ops = NULL; dev->netdev_ops = &nss_ipsecmgr_tunnel_ops; - dev->destructor = nss_ipsecmgr_tunnel_free; + dev->priv_destructor = nss_ipsecmgr_tunnel_free; /* * get the MAC address from the ethernet device --- a/ipsecmgr/v2.0/Makefile +++ b/ipsecmgr/v2.0/Makefile @@ -2,7 +2,7 @@ ccflags-y += $(NSS_CCFLAGS) -I$(obj)/../../exports ccflags-y += -DNSS_CLIENT_BUILD_ID="$(BUILD_ID)" -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-ipsecmgr.o qca-nss-ipsecmgr-objs := nss_ipsecmgr.o --- a/ipsecmgr/v2.0/nss_ipsecmgr.c +++ b/ipsecmgr/v2.0/nss_ipsecmgr.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -67,15 +67,6 @@ struct nss_ipsecmgr_drv *ipsecmgr_drv; static const struct net_device_ops nss_ipsecmgr_dummy_ndev_ops; /* - * nss_ipsecmgr_dummy_free() - * Setup function for dummy netdevice. - */ -static void nss_ipsecmgr_dummy_free(struct net_device *dev) -{ - free_netdev(dev); -} - -/* * nss_ipsecmgr_dummy_setup() * Setup function for dummy netdevice. */ @@ -86,11 +77,6 @@ static void nss_ipsecmgr_dummy_setup(str * transform. */ dev->mtu = ETH_DATA_LEN; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 8)) - dev->destructor = nss_ipsecmgr_dummy_free; -#else - dev->priv_destructor = nss_ipsecmgr_dummy_free; -#endif } /* @@ -110,9 +96,12 @@ static void nss_ipsecmgr_rx_notify(void static void nss_ipsecmgr_configure(struct work_struct *work) { enum nss_ipsec_cmn_msg_type type = NSS_IPSEC_CMN_MSG_TYPE_NODE_CONFIG; + struct nss_ipsecmgr_tunnel *tun = netdev_priv(ipsecmgr_drv->dev); uint32_t ifnum = ipsecmgr_drv->ifnum; struct nss_ipsec_cmn_msg nicm = {0}; + struct nss_ipsecmgr_ctx *redir; nss_tx_status_t status; + uint32_t vsi_num = 0; /* * By making sure that cryptoapi is registered, @@ -150,10 +139,6 @@ static void nss_ipsecmgr_configure(struc if (ipsecmgr_drv->ipsec_inline) { #ifdef NSS_IPSECMGR_PPE_SUPPORT - struct nss_ipsecmgr_tunnel *tun = netdev_priv(ipsecmgr_drv->dev); - struct nss_ipsecmgr_ctx *redir; - uint32_t vsi_num = 0; - redir = nss_ipsecmgr_ctx_alloc(tun, NSS_IPSEC_CMN_CTX_TYPE_REDIR, NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_REDIRECT, @@ -213,7 +198,7 @@ static void nss_ipsecmgr_configure(struc static int __init nss_ipsecmgr_init(void) { struct nss_ipsecmgr_tunnel *tun; - struct net_device *dev = NULL; + struct net_device *dev; int status; ipsecmgr_drv = vzalloc(sizeof(*ipsecmgr_drv)); @@ -251,7 +236,7 @@ static int __init nss_ipsecmgr_init(void status = register_netdev(dev); if (status) { nss_ipsecmgr_info("%px: Failed to register dummy netdevice(%px)", ipsecmgr_drv, dev); - goto free; + goto netdev_free; } ipsecmgr_drv->dev = dev; @@ -269,31 +254,41 @@ static int __init nss_ipsecmgr_init(void * Initialize debugfs. */ ipsecmgr_drv->dentry = debugfs_create_dir("qca-nss-ipsecmgr", NULL); - if (ipsecmgr_drv->dentry) { - tun->dentry = debugfs_create_dir(dev->name, ipsecmgr_drv->dentry); + if (!ipsecmgr_drv->dentry) { + nss_ipsecmgr_warn("%px: Failed to create root debugfs entry", ipsecmgr_drv); + nss_ipsec_cmn_notify_unregister(ipsecmgr_drv->nss_ctx, ipsecmgr_drv->ifnum); + goto unregister_dev; } /* + * Create debugfs entry for tunnel + */ + tun->dentry = debugfs_create_dir(dev->name, ipsecmgr_drv->dentry); + + /* * Configure inline mode and the DMA rings. */ nss_ipsecmgr_configure(&ipsecmgr_drv->cfg_work.work); - write_lock_bh(&ipsecmgr_drv->lock); + write_lock(&ipsecmgr_drv->lock); list_add(&tun->list, &ipsecmgr_drv->tun_db); ipsecmgr_drv->max_mtu = dev->mtu; - write_unlock_bh(&ipsecmgr_drv->lock); + write_unlock(&ipsecmgr_drv->lock); nss_ipsecmgr_info("NSS IPsec manager loaded: %s\n", NSS_CLIENT_BUILD_ID); return 0; +unregister_dev: + unregister_netdev(ipsecmgr_drv->dev); + +netdev_free: + free_netdev(ipsecmgr_drv->dev); + free: -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 8)) - if (dev) - dev->destructor(dev); -#endif vfree(ipsecmgr_drv); ipsecmgr_drv = NULL; + return -1; } --- a/ipsecmgr/v2.0/nss_ipsecmgr_ctx.c +++ b/ipsecmgr/v2.0/nss_ipsecmgr_ctx.c @@ -1,6 +1,6 @@ /* * ******************************************************************************** - * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. @@ -92,7 +92,6 @@ static const struct nss_ipsecmgr_print i {"\texceptioned", NSS_IPSECMGR_PRINT_DWORD}, {"\tlinearized", NSS_IPSECMGR_PRINT_DWORD}, {"\tredirected", NSS_IPSECMGR_PRINT_DWORD}, - {"\tdropped", NSS_IPSECMGR_PRINT_DWORD}, {"\tfail_sa", NSS_IPSECMGR_PRINT_DWORD}, {"\tfail_flow", NSS_IPSECMGR_PRINT_DWORD}, {"\tfail_stats", NSS_IPSECMGR_PRINT_DWORD}, @@ -100,9 +99,6 @@ static const struct nss_ipsecmgr_print i {"\tfail_transform", NSS_IPSECMGR_PRINT_DWORD}, {"\tfail_linearized", NSS_IPSECMGR_PRINT_DWORD}, {"\tfail_mdata_ver", NSS_IPSECMGR_PRINT_DWORD}, - {"\tfail_ctx_active", NSS_IPSECMGR_PRINT_DWORD}, - {"\tfail_pbuf_crypto", NSS_IPSECMGR_PRINT_DWORD}, - {"\tfail_queue_crypto", NSS_IPSECMGR_PRINT_DWORD}, }; /* @@ -552,8 +548,8 @@ void nss_ipsecmgr_ctx_rx_redir(struct ne * If, data callback is available then send the packet to the * callback function */ - if (tun->cb.except_cb) { - tun->cb.except_cb(tun->cb.app_data, skb); + if (tun->cb.data_cb) { + tun->cb.data_cb(tun->cb.app_data, skb); ctx->hstats.redir_cb++; return; } @@ -609,11 +605,6 @@ void nss_ipsecmgr_ctx_rx_outer(struct ne } skb_set_transport_header(skb, sizeof(*iph)); - if (tun->cb.except_cb) { - tun->cb.except_cb(tun->cb.app_data, skb); - ctx->hstats.outer_cb++; - return; - } nss_ipsecmgr_ctx_route_ipv4(skb, ctx); return; } @@ -631,11 +622,6 @@ void nss_ipsecmgr_ctx_rx_outer(struct ne } skb_set_transport_header(skb, sizeof(*ip6h)); - if (tun->cb.except_cb) { - tun->cb.except_cb(tun->cb.app_data, skb); - ctx->hstats.outer_cb++; - return; - } nss_ipsecmgr_ctx_route_ipv6(skb, ctx); return; } @@ -731,7 +717,6 @@ void nss_ipsecmgr_ctx_rx_stats(void *app struct nss_ipsecmgr_sa *sa; void *app_data; - event.type = NSS_IPSECMGR_EVENT_SA_STATS; write_lock(&ipsecmgr_drv->lock); sa = nss_ipsecmgr_sa_find(sa_db, &sync->sa_tuple); @@ -874,30 +859,13 @@ struct nss_ipsecmgr_ctx *nss_ipsecmgr_ct } /* - * nss_ipsecmgr_ctx_attach() - * Attach context to the database - */ -void nss_ipsecmgr_ctx_attach(struct list_head *db, struct nss_ipsecmgr_ctx *ctx) -{ - struct nss_ipsecmgr_tunnel *tun = ctx->tun; - - list_add(&ctx->list, db); - - /* - * Add ctx->ref to tun->ref - */ - write_lock_bh(&ipsecmgr_drv->lock); - nss_ipsecmgr_ref_add(&ctx->ref, &tun->ref); - write_unlock_bh(&ipsecmgr_drv->lock); -} - -/* * nss_ipsecmgr_ctx_config() * Configure context */ bool nss_ipsecmgr_ctx_config(struct nss_ipsecmgr_ctx *ctx) { enum nss_ipsec_cmn_msg_type msg_type = NSS_IPSEC_CMN_MSG_TYPE_CTX_CONFIG; + struct nss_ipsecmgr_tunnel *tun = ctx->tun; struct nss_ipsec_cmn_ctx *ctx_msg; struct nss_ipsec_cmn_msg nicm; nss_tx_status_t status; @@ -907,7 +875,6 @@ bool nss_ipsecmgr_ctx_config(struct nss_ ctx_msg = &nicm.msg.ctx; ctx_msg->type = ctx->state.type; ctx_msg->except_ifnum = ctx->state.except_ifnum; - ctx_msg->sibling_ifnum = ctx->state.sibling_ifnum; status = nss_ipsec_cmn_tx_msg_sync(ctx->nss_ctx, ctx->ifnum, msg_type, sizeof(*ctx_msg), &nicm); if (status != NSS_TX_SUCCESS) { @@ -916,6 +883,10 @@ bool nss_ipsecmgr_ctx_config(struct nss_ return false; } + write_lock_bh(&ipsecmgr_drv->lock); + nss_ipsecmgr_ref_add(&ctx->ref, &tun->ref); + write_unlock_bh(&ipsecmgr_drv->lock); + return true; } @@ -941,7 +912,6 @@ struct nss_ipsecmgr_ctx *nss_ipsecmgr_ct uint32_t features) { struct nss_ipsecmgr_ctx *ctx; - int32_t ifnum; ctx = kzalloc(sizeof(*ctx), in_atomic() ? GFP_ATOMIC : GFP_KERNEL); if (!ctx) { @@ -955,14 +925,13 @@ struct nss_ipsecmgr_ctx *nss_ipsecmgr_ct ctx->state.type = ctx_type; ctx->state.di_type = di_type; - ifnum = nss_dynamic_interface_alloc_node(di_type); - if (ifnum < 0) { + ctx->ifnum = nss_dynamic_interface_alloc_node(di_type); + if (ctx->ifnum < 0) { nss_ipsecmgr_warn("%px: failed to allocate dynamic interface(%d)", tun, di_type); kfree(ctx); return NULL; } - ctx->ifnum = ifnum; ctx->state.stats_len = ctx->state.print_len = nss_ipsecmgr_ctx_stats_size(); nss_ipsecmgr_ref_init(&ctx->ref, nss_ipsecmgr_ctx_del_ref, nss_ipsecmgr_ctx_free_ref); nss_ipsecmgr_ref_init_print(&ctx->ref, nss_ipsecmgr_ctx_print_len, nss_ipsecmgr_ctx_print); --- a/ipsecmgr/v2.0/nss_ipsecmgr_ctx.h +++ b/ipsecmgr/v2.0/nss_ipsecmgr_ctx.h @@ -43,7 +43,7 @@ struct nss_ipsecmgr_ctx_host_stats { uint64_t inner_fail_flow; /* Failed to find flow for inner packet */ uint64_t outer_exp; /* Host processed inner IPv6 exceptioned packet */ uint64_t outer_exp_drop; /* Host processed and dropped inner IPv6 exceptioned packet */ - uint64_t outer_cb; /* Number of times exception call back called for outer packet */ + uint64_t outer_cb; /* Number of times data call back called for inner packet */ uint64_t outer_fail_dev; /* Failed to find netdevice for inner packet */ uint64_t outer_fail_sa; /* Failed to find SA for outer packet */ uint64_t outer_fail_flow; /* Failed to find flow for outer packet */ @@ -70,7 +70,6 @@ struct nss_ipsecmgr_ctx_stats_priv { uint64_t exceptioned; /* Exceptioned to host */ uint64_t linearized; /* Linearized packets */ uint64_t redirected; /* Redirected from inline */ - uint64_t dropped; /* Total dropped packets */ uint64_t fail_sa; /* Failed to find SA */ uint64_t fail_flow; /* Failed to find flow */ uint64_t fail_stats; /* Failed to send statistics */ @@ -78,9 +77,6 @@ struct nss_ipsecmgr_ctx_stats_priv { uint64_t fail_transform; /* Failed to transform */ uint64_t fail_linearized; /* Failed to linearized */ uint64_t fail_mdata_ver; /* Invalid meta data version */ - uint64_t fail_ctx_active; /* Failed to queue as ctx is not active. */ - uint64_t fail_pbuf_crypto; /* Failed to allocate pbuf for crypto operation */ - uint64_t fail_queue_crypto; /* Failed to queue pbuf to crypto pnode */ }; /* @@ -90,7 +86,6 @@ struct nss_ipsecmgr_ctx_state { ssize_t print_len; /* Print buffer length */ ssize_t stats_len; /* Total stats length */ uint32_t except_ifnum; /* Exception interface number */ - uint32_t sibling_ifnum; /* Sibling interface number */ enum nss_ipsec_cmn_ctx_type type; /* Type */ enum nss_dynamic_interface_type di_type; /* Dynamic interface type */ }; @@ -112,19 +107,20 @@ struct nss_ipsecmgr_ctx { }; /* - * Set the exception interface number for context + * nss_ipsecmgr_ctx_attach() + * Attach context to the database */ -static inline void nss_ipsecmgr_ctx_set_except(struct nss_ipsecmgr_ctx *ctx, uint32_t except_ifnum) +static inline void nss_ipsecmgr_ctx_attach(struct list_head *db, struct nss_ipsecmgr_ctx *ctx) { - ctx->state.except_ifnum = except_ifnum; + list_add(&ctx->list, db); } /* - * Set the sibling interface number for context + * Set the exception interface number for context */ -static inline void nss_ipsecmgr_ctx_set_sibling(struct nss_ipsecmgr_ctx *ctx, uint32_t sibling_ifnum) +static inline void nss_ipsecmgr_ctx_set_except(struct nss_ipsecmgr_ctx *ctx, uint32_t except_ifnum) { - ctx->state.sibling_ifnum = sibling_ifnum; + ctx->state.except_ifnum = except_ifnum; } extern const struct file_operations ipsecmgr_ctx_file_ops; @@ -135,7 +131,6 @@ extern void nss_ipsecmgr_ctx_rx_redir(st extern void nss_ipsecmgr_ctx_rx_outer(struct net_device *dev, struct sk_buff *skb, struct napi_struct *napi); extern void nss_ipsecmgr_ctx_rx_inner(struct net_device *dev, struct sk_buff *skb, struct napi_struct *napi); -extern void nss_ipsecmgr_ctx_attach(struct list_head *db, struct nss_ipsecmgr_ctx *ctx); extern bool nss_ipsecmgr_ctx_config(struct nss_ipsecmgr_ctx *ctx); extern void nss_ipsecmgr_ctx_free(struct nss_ipsecmgr_ctx *ctx); extern struct nss_ipsecmgr_ctx *nss_ipsecmgr_ctx_alloc(struct nss_ipsecmgr_tunnel *tun, --- a/ipsecmgr/v2.0/nss_ipsecmgr_flow.c +++ b/ipsecmgr/v2.0/nss_ipsecmgr_flow.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -149,10 +149,10 @@ static bool nss_ipsecmgr_flow_update_db( hash_idx = nss_ipsecmgr_flow_tuple2hash(&flow->state.tuple, NSS_IPSECMGR_FLOW_MAX); - write_lock_bh(&ipsecmgr_drv->lock); + write_lock(&ipsecmgr_drv->lock); sa = nss_ipsecmgr_sa_find(ipsecmgr_drv->sa_db, sa_tuple); if (!sa) { - write_unlock_bh(&ipsecmgr_drv->lock); + write_unlock(&ipsecmgr_drv->lock); nss_ipsecmgr_trace("%px: failed to find SA during flow update", flow); return false; } @@ -163,7 +163,7 @@ static bool nss_ipsecmgr_flow_update_db( */ nss_ipsecmgr_ref_add(&flow->ref, &sa->ref); list_add(&flow->list, &ipsecmgr_drv->flow_db[hash_idx]); - write_unlock_bh(&ipsecmgr_drv->lock); + write_unlock(&ipsecmgr_drv->lock); return true; } @@ -215,7 +215,7 @@ static void nss_ipsecmgr_flow_del_ref(st * Write lock needs to be held by the caller since flow db is * getting modified. */ - nss_ipsecmgr_write_lock_is_held(&ipsecmgr_drv->lock); + BUG_ON(write_can_lock(&ipsecmgr_drv->lock)); list_del_init(&flow->list); } --- a/ipsecmgr/v2.0/nss_ipsecmgr_priv.h +++ b/ipsecmgr/v2.0/nss_ipsecmgr_priv.h @@ -1,6 +1,6 @@ /* * ******************************************************************************** - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. @@ -20,8 +20,6 @@ #define __NSS_IPSECMGR_PRIV_H #include -#include -#include #define NSS_IPSECMGR_DEBUG_LVL_ERROR 1 /**< Turn on debug for an error. */ #define NSS_IPSECMGR_DEBUG_LVL_WARN 2 /**< Turn on debug for a warning. */ @@ -78,16 +76,6 @@ #define NSS_IPSECMGR_PRINT_SHORT NSS_IPSECMGR_PRINT_BYTES(2) #define NSS_IPSECMGR_PRINT_BYTE NSS_IPSECMGR_PRINT_BYTES(1) #define NSS_IPSECMGR_PRINT_IPADDR (NSS_IPSECMGR_PRINT_WORD * 4) -/* - * Check if lock is held - */ -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 14, 196)) -#define nss_ipsecmgr_write_lock_is_held(x) BUG_ON(write_can_lock(x)) -#define nss_ipsecmgr_lock_is_held(x) BUG_ON(read_can_lock(x)) -#else -#define nss_ipsecmgr_lock_is_held(x) lockdep_assert_held(x) -#define nss_ipsecmgr_write_lock_is_held(x) lockdep_assert_held_write(x) -#endif /* * Statistics dump information --- a/ipsecmgr/v2.0/nss_ipsecmgr_ref.c +++ b/ipsecmgr/v2.0/nss_ipsecmgr_ref.c @@ -140,7 +140,7 @@ ssize_t nss_ipsecmgr_ref_print(struct ns /* * DEBUG check to see if the lock is taken before touching the list */ - nss_ipsecmgr_write_lock_is_held(&ipsecmgr_drv->lock); + BUG_ON(write_can_lock(&ipsecmgr_drv->lock)); len += ref->print(ref, buf); @@ -163,7 +163,7 @@ ssize_t nss_ipsecmgr_ref_print_len(struc /* * DEBUG check to see if the lock is taken before touching the list */ - nss_ipsecmgr_write_lock_is_held(&ipsecmgr_drv->lock); + BUG_ON(write_can_lock(&ipsecmgr_drv->lock)); list_for_each_entry(entry, &ref->head, node) { total_len += nss_ipsecmgr_ref_print_len(entry); @@ -203,7 +203,7 @@ void nss_ipsecmgr_ref_del(struct nss_ips /* * DEBUG check to see if the lock is taken before touching the list */ - nss_ipsecmgr_write_lock_is_held(&ipsecmgr_drv->lock); + BUG_ON(write_can_lock(&ipsecmgr_drv->lock)); while (!list_empty(&ref->head)) { entry = list_first_entry(&ref->head, struct nss_ipsecmgr_ref, node); @@ -231,7 +231,7 @@ void nss_ipsecmgr_ref_add(struct nss_ips /* * DEBUG check to see if the lock is taken before touching the list */ - nss_ipsecmgr_write_lock_is_held(&ipsecmgr_drv->lock); + BUG_ON(write_can_lock(&ipsecmgr_drv->lock)); /* * if child is already part of an existing chain then remove it before --- a/ipsecmgr/v2.0/nss_ipsecmgr_ref.h +++ b/ipsecmgr/v2.0/nss_ipsecmgr_ref.h @@ -1,6 +1,6 @@ /* * ******************************************************************************** - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. @@ -42,12 +42,6 @@ struct nss_ipsecmgr_ref { nss_ipsecmgr_ref_method_t del; /* unlink function */ }; -/* Check if the reference tree is empty */ -static inline bool nss_ipsecmgr_ref_is_empty(struct nss_ipsecmgr_ref *ref) -{ - return list_empty(&ref->head); -} - /* functions to operate on reference object */ extern ssize_t nss_ipsecmgr_ref_print_len(struct nss_ipsecmgr_ref *ref); extern ssize_t nss_ipsecmgr_ref_print(struct nss_ipsecmgr_ref *ref, char *buf); --- a/ipsecmgr/v2.0/nss_ipsecmgr_sa.c +++ b/ipsecmgr/v2.0/nss_ipsecmgr_sa.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -130,7 +130,6 @@ static const struct nss_ipsecmgr_print i {"\tfail_transform", NSS_IPSECMGR_PRINT_DWORD}, {"\tfail_crypto", NSS_IPSECMGR_PRINT_DWORD}, {"\tfail_classification", NSS_IPSECMGR_PRINT_DWORD}, - {"\tis_stopped", NSS_IPSECMGR_PRINT_DWORD}, }; /* @@ -364,7 +363,6 @@ static nss_ipsecmgr_status_t nss_ipsecmg if (!rt_keys) { nss_ipsecmgr_warn("%px: failed to allocate key memory\n", sa); crypto_free_aead(sa->aead); - sa->aead = NULL; return NSS_IPSECMGR_FAIL_NOMEM; } @@ -390,7 +388,6 @@ static nss_ipsecmgr_status_t nss_ipsecmg if (crypto_aead_setkey(sa->aead, rt_keys, keylen)) { nss_ipsecmgr_warn("%px: failed to configure keys\n", sa); crypto_free_aead(sa->aead); - sa->aead = NULL; vfree(rt_keys); return NSS_IPSECMGR_INVALID_KEYLEN; } @@ -417,7 +414,6 @@ static nss_ipsecmgr_status_t nss_ipsecmg if (crypto_ahash_setkey(sa->ahash, keys->auth_key, keys->auth_keylen)) { nss_ipsecmgr_warn("%px: failed to configure keys\n", sa); crypto_free_ahash(sa->ahash); - sa->ahash = NULL; return NSS_IPSECMGR_INVALID_KEYLEN; } @@ -448,7 +444,6 @@ static nss_ipsecmgr_status_t nss_ipsecmg if (!rt_keys) { nss_ipsecmgr_warn("%px: failed to allocate key memory\n", sa); crypto_free_aead(sa->aead); - sa->aead = NULL; return NSS_IPSECMGR_FAIL_NOMEM; } @@ -458,7 +453,6 @@ static nss_ipsecmgr_status_t nss_ipsecmg if (crypto_aead_setkey(sa->aead, rt_keys, keylen)) { nss_ipsecmgr_warn("%px: failed to configure keys\n", sa); crypto_free_aead(sa->aead); - sa->aead = NULL; vfree(rt_keys); return NSS_IPSECMGR_INVALID_KEYLEN; } @@ -486,15 +480,11 @@ static nss_ipsecmgr_status_t nss_ipsecmg */ static void nss_ipsecmgr_sa_free(struct nss_ipsecmgr_sa *sa) { - if (sa->aead) { + if (sa->aead) crypto_free_aead(sa->aead); - sa->aead = NULL; - } - if (sa->ahash) { + if (sa->ahash) crypto_free_ahash(sa->ahash); - sa->ahash = NULL; - } kfree(sa); } @@ -513,7 +503,7 @@ static void nss_ipsecmgr_sa_del_ref(stru * Linux does not provide any specific API(s) to test for RW locks. The caller * being internal is assumed to hold write lock before initiating this. */ - nss_ipsecmgr_write_lock_is_held(&ipsecmgr_drv->lock); + BUG_ON(write_can_lock(&ipsecmgr_drv->lock)); list_del_init(&sa->list); @@ -789,10 +779,6 @@ void nss_ipsecmgr_sa_sync2stats(struct n stats->seq_start = sync->replay.seq_start; stats->seq_cur = sync->replay.seq_cur; } - - stats->fail_replay_win = sa_stats->fail_replay_win; - stats->fail_replay_dup = sa_stats->fail_replay_dup; - stats->fail_auth = sa_stats->fail_auth; } /* @@ -809,7 +795,7 @@ void nss_ipsecmgr_sa_sync_state(struct n * DEBUG check to see if the lock is taken before accessing * SA entry in the database */ - nss_ipsecmgr_write_lock_is_held(&ipsecmgr_drv->lock); + BUG_ON(write_can_lock(&ipsecmgr_drv->lock)); for (num = 0; num < sizeof(sa->stats)/sizeof(*sa_stats); num++) { sa_stats[num] += msg_stats[num]; @@ -1082,85 +1068,6 @@ bool nss_ipsecmgr_sa_verify(struct net_d EXPORT_SYMBOL(nss_ipsecmgr_sa_verify); /* - * nss_ipsecmgr_cra_name2algo() - * Returns nss_ipsecmgr_algo - */ -enum nss_ipsecmgr_algo nss_ipsecmgr_cra_name2algo(const char *cra_name) -{ - enum nss_ipsecmgr_algo algo = NSS_IPSECMGR_ALGO_AES_CBC_SHA1_HMAC; - const char **algo_name = ipsecmgr_algo_name; - - for (; algo < NSS_IPSECMGR_ALGO_MAX; algo++, algo_name++) { - if (!strncmp(cra_name, *algo_name, strlen(*algo_name))) { - return algo; - } - } - - return NSS_IPSECMGR_ALGO_MAX; -} -EXPORT_SYMBOL(nss_ipsecmgr_cra_name2algo); - -/* - * nss_ipsecmgr_sa_get_info() - * Get Crypto information for an already created SA. - */ -bool nss_ipsecmgr_sa_get_info(struct net_device *dev, struct nss_ipsecmgr_sa_tuple *tuple, - struct nss_ipsecmgr_sa_info *sa_info) -{ - struct nss_ipsec_cmn_sa_tuple sa_tuple = {0}; - struct nss_ipsecmgr_sa *sa; - uint32_t mask; - - /* - * Look for an existing SA. - */ - nss_ipsecmgr_sa2tuple(tuple, &sa_tuple); - - read_lock_bh(&ipsecmgr_drv->lock); - sa = nss_ipsecmgr_sa_find(ipsecmgr_drv->sa_db, &sa_tuple); - if (!sa) { - read_unlock_bh(&ipsecmgr_drv->lock); - return false; - } - - sa_info->blk_len = sa->state.data.blk_len; - sa_info->iv_len = sa->state.data.iv_len; - sa_info->hash_len = sa->state.data.icv_len; - sa_info->session_idx = sa->state.tuple.crypto_index; - - sa_info->hdr_len = sizeof(struct ip_esp_hdr) + sa_info->iv_len; - mask = NSS_IPSEC_CMN_FLAG_HDR_MASK | NSS_IPSEC_CMN_FLAG_MODE_TRANS; - - switch (sa->state.data.flags & mask) { - case NSS_IPSEC_CMN_FLAG_IPV4_NATT | NSS_IPSEC_CMN_FLAG_MODE_TRANS: - sa_info->hdr_len += sizeof(struct udphdr); - break; - case NSS_IPSEC_CMN_FLAG_IPV6 | NSS_IPSEC_CMN_FLAG_MODE_TRANS: - case NSS_IPSEC_CMN_FLAG_MODE_TRANS: - break; - case NSS_IPSEC_CMN_FLAG_IPV4_NATT: - sa_info->hdr_len += sizeof(struct iphdr) + sizeof(struct udphdr); - break; - case NSS_IPSEC_CMN_FLAG_IPV6: - sa_info->hdr_len += sizeof(struct ipv6hdr); - break; - default: - sa_info->hdr_len += sizeof(struct iphdr); - break; - } - - read_unlock_bh(&ipsecmgr_drv->lock); - - /* - * The user of trailer_len should take care of the odd length. - */ - sa_info->trailer_len = sa_info->blk_len + 1 + sa_info->hash_len; - - return true; -} -EXPORT_SYMBOL(nss_ipsecmgr_sa_get_info); - -/* * nss_ipsecmgr_sa_tx_inner() * Offload given SKB to NSS for inner processing. */ --- a/ipsecmgr/v2.0/nss_ipsecmgr_sa.h +++ b/ipsecmgr/v2.0/nss_ipsecmgr_sa.h @@ -1,6 +1,6 @@ /* * ******************************************************************************** - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. @@ -62,8 +62,7 @@ struct nss_ipsecmgr_sa_stats_priv { uint64_t fail_hash_len; /**< Failure in decap due to bad hash block len. */ uint64_t fail_transform; /**< Failure in transformation; general error. */ uint64_t fail_crypto; /**< Failure in crypto transformation. */ - uint64_t fail_cle; /**< Failure in classification; general failure */ - uint64_t is_stopped; /**< Indicates if SA is stopped; eg: seq overflow */ + uint64_t fail_cle; /* Failure in classification; general failure */ }; /* --- a/ipsecmgr/v2.0/nss_ipsecmgr_tunnel.c +++ b/ipsecmgr/v2.0/nss_ipsecmgr_tunnel.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -128,14 +128,6 @@ static netdev_tx_t nss_ipsecmgr_tunnel_t } /* - * Linearize the nonlinear SKB. - */ - if (skb_linearize(skb)) { - nss_ipsecmgr_trace("%s: unable to Linearize SKB\n", dev->name); - goto free; - } - - /* * For all these cases * - create a writable copy of buffer * - increase the head room @@ -227,10 +219,10 @@ free: } /* - * nss_ipsecmgr_tunnel_get_stats64() + * nss_ipsecmgr_tunnel_stats64() * Get device statistics */ -static struct rtnl_link_stats64 *nss_ipsecmgr_tunnel_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) +static struct rtnl_link_stats64 *nss_ipsecmgr_tunnel_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { struct nss_ipsecmgr_tunnel *tun = netdev_priv(dev); struct list_head *head = &tun->ctx_db; @@ -248,22 +240,6 @@ static struct rtnl_link_stats64 *nss_ips } /* - * nss_ipsecmgr_tunnel_stats64() - * Sync statistics to linux - */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)) -static struct rtnl_link_stats64 *nss_ipsecmgr_tunnel_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) -{ - return nss_ipsecmgr_tunnel_get_stats64(dev, stats); -} -#else -static void nss_ipsecmgr_tunnel_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) -{ - nss_ipsecmgr_tunnel_get_stats64(dev, stats); -} -#endif - -/* * nss_ipsecmgr_tunnel_mtu_update() * Update tunnel max MTU */ @@ -273,7 +249,7 @@ static void nss_ipsecmgr_tunnel_mtu_upda uint16_t max_mtu = 0; bool update_mtu = false; - write_lock_bh(&ipsecmgr_drv->lock); + write_lock(&ipsecmgr_drv->lock); list_for_each_entry(tun, head, list) { if (tun->dev->mtu > max_mtu) max_mtu = tun->dev->mtu; @@ -284,7 +260,7 @@ static void nss_ipsecmgr_tunnel_mtu_upda update_mtu = true; } - write_unlock_bh(&ipsecmgr_drv->lock); + write_unlock(&ipsecmgr_drv->lock); #ifdef NSS_IPSECMGR_PPE_SUPPORT /* @@ -337,29 +313,7 @@ static const struct net_device_ops ipsec */ static void nss_ipsecmgr_tunnel_free(struct net_device *dev) { - struct nss_ipsecmgr_tunnel *tun = netdev_priv(dev); - struct nss_ipsecmgr_ref *ref, *tmp; - struct list_head free_refs; - nss_ipsecmgr_info("IPsec tunnel device(%s) freed\n", dev->name); - - INIT_LIST_HEAD(&free_refs); - - /* - * Remove context(s) from the tunnel reference tree if it has been - * added - */ - write_lock_bh(&ipsecmgr_drv->lock); - if (!nss_ipsecmgr_ref_is_empty(&tun->ref)) { - nss_ipsecmgr_ref_del(&tun->ref, &free_refs); - } - - write_unlock_bh(&ipsecmgr_drv->lock); - - list_for_each_entry_safe(ref, tmp, &free_refs, node) { - ref->free(ref); - } - free_netdev(dev); } @@ -397,14 +351,13 @@ static void nss_ipsecmgr_tunnel_free_ref { struct nss_ipsecmgr_tunnel *tun = container_of(ref, struct nss_ipsecmgr_tunnel, ref); + nss_ipsecmgr_tunnel_mtu_update(&ipsecmgr_drv->tun_db); + /* * The unregister should start here but the expectation is that the free would * happen when the reference count goes down to '0' */ - if (tun->dev->reg_state == NETREG_REGISTERED) { - nss_ipsecmgr_tunnel_mtu_update(&ipsecmgr_drv->tun_db); - rtnl_is_locked() ? unregister_netdevice(tun->dev) : unregister_netdev(tun->dev); - } + rtnl_is_locked() ? unregister_netdevice(tun->dev) : unregister_netdev(tun->dev); } /* @@ -436,11 +389,7 @@ static void nss_ipsecmgr_tunnel_setup(st dev->header_ops = NULL; dev->netdev_ops = &ipsecmgr_dev_ops; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 8)) dev->destructor = nss_ipsecmgr_tunnel_free; -#else - dev->priv_destructor = nss_ipsecmgr_tunnel_free; -#endif /* * Get the MAC address from the ethernet device @@ -524,11 +473,9 @@ struct net_device *nss_ipsecmgr_tunnel_a NSS_IPSEC_CMN_FEATURE_INLINE_ACCEL); if (!inner) { nss_ipsecmgr_warn("%px: failed to allocate context inner\n", tun); - goto free; + goto free_dev; } - nss_ipsecmgr_ctx_attach(&tun->ctx_db, inner); - /* * Inner Metadata context allocation */ @@ -540,10 +487,9 @@ struct net_device *nss_ipsecmgr_tunnel_a 0); if (!mdata_inner) { nss_ipsecmgr_warn("%px: failed to allocate context metadata inner\n", tun); - goto free; + goto free_inner; } - nss_ipsecmgr_ctx_attach(&tun->ctx_db, mdata_inner); /* * Outer context allocation */ @@ -555,10 +501,9 @@ struct net_device *nss_ipsecmgr_tunnel_a NSS_IPSEC_CMN_FEATURE_INLINE_ACCEL); if (!outer) { nss_ipsecmgr_warn("%px: failed to allocate context outer\n", tun); - goto free; + goto free_mdata_inner; } - nss_ipsecmgr_ctx_attach(&tun->ctx_db, outer); /* * Outer metadata context allocation */ @@ -570,9 +515,13 @@ struct net_device *nss_ipsecmgr_tunnel_a 0); if (!mdata_outer) { nss_ipsecmgr_warn("%px: failed to allocate context metadata outer\n", tun); - goto free; + goto free_outer; } + nss_ipsecmgr_ctx_attach(&tun->ctx_db, inner); + nss_ipsecmgr_ctx_attach(&tun->ctx_db, mdata_inner); + + nss_ipsecmgr_ctx_attach(&tun->ctx_db, outer); nss_ipsecmgr_ctx_attach(&tun->ctx_db, mdata_outer); /* @@ -587,49 +536,35 @@ struct net_device *nss_ipsecmgr_tunnel_a nss_ipsecmgr_ctx_set_except(outer, inner->ifnum); nss_ipsecmgr_ctx_set_except(mdata_outer, inner->ifnum); - /* - * We need to setup the sibling interface number for inner & outer; - * The sibling interface is used by the NSS to configure SA on sibling. - */ - nss_ipsecmgr_ctx_set_sibling(inner, mdata_inner->ifnum); - nss_ipsecmgr_ctx_set_sibling(outer, mdata_outer->ifnum); - if (!nss_ipsecmgr_ctx_config(inner)) { nss_ipsecmgr_warn("%px: failed to configure inner context\n", tun); - goto free; + goto free_mdata_outer; } if (!nss_ipsecmgr_ctx_config(mdata_inner)) { nss_ipsecmgr_warn("%px: failed to configure metadata inner context\n", tun); - goto free; + goto free_mdata_outer; } if (!nss_ipsecmgr_ctx_config(outer)) { nss_ipsecmgr_warn("%px: failed to configure outer context\n", tun); - goto free; + goto free_mdata_outer; } if (!nss_ipsecmgr_ctx_config(mdata_outer)) { nss_ipsecmgr_warn("%px: failed to configure metadata outer context\n", tun); - goto free; + goto free_mdata_outer; } status = rtnl_is_locked() ? register_netdevice(dev) : register_netdev(dev); if (status < 0) { nss_ipsecmgr_warn("%px: register net dev failed :%s\n", tun, dev->name); -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 8)) - goto free; -#else - /* - * Later kernels invoke the destructor upon failure - */ - return NULL; -#endif + goto free_mdata_outer; } - write_lock_bh(&ipsecmgr_drv->lock); + write_lock(&ipsecmgr_drv->lock); list_add(&tun->list, &ipsecmgr_drv->tun_db); - write_unlock_bh(&ipsecmgr_drv->lock); + write_unlock(&ipsecmgr_drv->lock); nss_ipsecmgr_tunnel_mtu(dev, skb_dev ? skb_dev->mtu : dev->mtu); @@ -645,12 +580,16 @@ struct net_device *nss_ipsecmgr_tunnel_a } return dev; -free: -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 8)) - dev->destructor(dev); -#else - dev->priv_destructor(dev); -#endif +free_mdata_outer: + nss_ipsecmgr_ctx_free(mdata_outer); +free_outer: + nss_ipsecmgr_ctx_free(outer); +free_mdata_inner: + nss_ipsecmgr_ctx_free(mdata_inner); +free_inner: + nss_ipsecmgr_ctx_free(inner); +free_dev: + free_netdev(dev); return NULL; } EXPORT_SYMBOL(nss_ipsecmgr_tunnel_add); --- a/ipsecmgr/v2.0/plugins/klips/Makefile +++ b/ipsecmgr/v2.0/plugins/klips/Makefile @@ -10,7 +10,7 @@ ccflags-y += -I$(obj)/../../include ccflags-y += -I$(obj)/ ccflags-y += -DNSS_IPSEC_KLIPS_DEBUG_LEVEL=3 ccflags-y += -DNSS_IPSEC_KLIPS_BUILD_ID="$(BUILD_ID)" -ccflags-y += -Wall -Werror +ccflags-y += -Werror ifeq ($(SoC),$(filter $(SoC),ipq807x ipq807x_64)) ccflags-y += -DNSS_CFI_IPQ807X_SUPPORT endif @@ -18,7 +18,3 @@ endif ifeq ($(SoC),$(filter $(SoC),ipq60xx ipq60xx_64)) ccflags-y += -DNSS_CFI_IPQ60XX_SUPPORT endif - -ifeq ($(SoC),$(filter $(SoC),ipq50xx ipq50xx_64)) -ccflags-y += -DNSS_CFI_IPQ50XX_SUPPORT -endif --- a/ipsecmgr/v2.0/plugins/klips/nss_ipsec_klips.c +++ b/ipsecmgr/v2.0/plugins/klips/nss_ipsec_klips.c @@ -1,5 +1,4 @@ -/* - * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -13,10 +12,11 @@ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * */ -/* - * nss_ipsec_klips.c +/* nss_ipsec_klips.c * NSS IPsec offload glue for Openswan/KLIPS */ #include @@ -51,9 +51,6 @@ #if defined(NSS_L2TPV2_ENABLED) #include #endif -#if defined(NSS_VXLAN_ENABLED) -#include -#endif #include "nss_ipsec_klips.h" #define NSS_IPSEC_KLIPS_BASE_NAME "ipsec" @@ -62,7 +59,6 @@ #define NSS_IPSEC_KLIPS_FLAG_NATT 0x00000001 #define NSS_IPSEC_KLIPS_FLAG_TRANSPORT_MODE 0x00000002 #define NSS_IPSEC_KLIPS_SKB_CB_MAGIC 0xAAAB -#define NSS_IPSEC_KLIPS_IP6_ADDR_LEN 4 /* * This is used by KLIPS for communicate the device along with the @@ -348,32 +344,6 @@ static struct net_device *nss_ipsec_klip return tun_dev; } -#if defined(NSS_L2TPV2_ENABLED) -/* - * nss_ipsec_klips_get_inner_ifnum() - * Get ipsecmgr interface number for klips netdevice - * - * Calls nss_ipsec_klips_get_tun_dev(), which holds reference for tunnel, - * which gets released at the end of this function. - */ -static int nss_ipsec_klips_get_inner_ifnum(struct net_device *klips_dev) -{ - struct net_device *tun_dev; - int32_t ipsec_ifnum; - - tun_dev = nss_ipsec_klips_get_tun_dev(klips_dev); - if (!tun_dev) { - nss_ipsec_klips_warn("%px: Tunnel device not found for klips dev", klips_dev); - return -1; - } - - ipsec_ifnum = nss_cmn_get_interface_number_by_dev_and_type(tun_dev, NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_INNER); - dev_put(tun_dev); - - return ipsec_ifnum; -} -#endif - /* * nss_ipsec_klips_get_tun_by_addr() * Get the tunnel entry for given ip header from tunnel map table. @@ -402,75 +372,6 @@ static struct nss_ipsec_klips_tun *nss_i return NULL; } -#if defined(NSS_VXLAN_ENABLED) -/* - * nss_ipsec_klips_tun_match_ip_addr() - * Compare tunnel address with source & destination ip addresses. - */ -static bool nss_ipsec_klips_tun_match_ip_addr(struct nss_ipsec_klips_tun *tun, uint8_t ip_ver, uint32_t *local_ip, uint32_t *remote_ip) -{ - struct nss_ipsec_klips_tun_addr *addr = &tun->addr; - uint32_t status = 0; - uint8_t i; - - switch (ip_ver) { - case IPVERSION: - status += local_ip[0] ^ addr->dest[0]; - status += remote_ip[0] ^ addr->src[0]; - status += addr->ver ^ ip_ver; - nss_ipsec_klips_trace("%px: tun dev comparing with IPV4 tunnel local_ip: %x & remote_ip: %x IP pair.\n", tun, addr->dest[0], addr->src[0]); - return !status; - - case 6: - status += addr->ver ^ ip_ver; - for (i = 0; i < NSS_IPSEC_KLIPS_IP6_ADDR_LEN; i++) { - status += local_ip[i] ^ addr->dest[i]; - status += remote_ip[i] ^ addr->src[i]; - nss_ipsec_klips_trace("%px: tun dev comparing with IPV6 tunnel local_ip[%u]: %x & remote_ip[%u]: %x IP pair.\n", tun, i, addr->dest[i], i, addr->src[i]); - } - return !status; - - default: - nss_ipsec_klips_warn("%px: non ip version:%u received", tun, ip_ver); - return false; - } -} - -/* - * nss_ipsec_klips_get_ipsec_ifnum() - * Get ipsecmgr tunnel interface num for klips netdevice - */ -static int32_t __maybe_unused nss_ipsec_klips_get_ipsec_ifnum(uint8_t ip_ver, uint32_t *local_ip, uint32_t *remote_ip) -{ - struct nss_ipsec_klips_tun *tun; - struct net_device *tun_dev; - uint32_t if_num = -1; - uint32_t i; - - read_lock(&tunnel_map.lock); - - for (i = 0, tun = tunnel_map.tbl; i < tunnel_map.max; i++, tun++) { - if (!tun->klips_dev) { - nss_ipsec_klips_warn("%px: klips dev is NULL.\n", tun); - continue; - } - - if (nss_ipsec_klips_tun_match_ip_addr(tun, ip_ver, local_ip, remote_ip)) { - tun_dev = tun->nss_dev; - if_num = nss_cmn_get_interface_number_by_dev_and_type(tun_dev, NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_INNER); - nss_ipsec_klips_warn("%px: tun dev(with ifnum:%d) is mapped with local & remote IP pair.\n", tun, if_num); - read_unlock(&tunnel_map.lock); - return if_num; - } - } - - read_unlock(&tunnel_map.lock); - - nss_ipsec_klips_warn("%px: tun dev not found with the local(%pI4) & remote(%pI4) IP pair.\n", tun, local_ip, remote_ip); - return -1; -} -#endif - /* * nss_ipsec_klips_get_index() * given an interface name retrived the numeric suffix @@ -2070,14 +1971,7 @@ static struct notifier_block nss_ipsec_k #if defined(NSS_L2TPV2_ENABLED) static struct l2tpmgr_ipsecmgr_cb nss_ipsec_klips_l2tp = { - .get_ifnum_by_dev = nss_ipsec_klips_get_inner_ifnum, - .get_ifnum_by_ip_addr = NULL -}; -#endif - -#if defined(NSS_VXLAN_ENABLED) -static struct nss_vxlanmgr_get_ipsec_if_num nss_ipsec_klips_vxlan_cb = { - .get_ifnum_by_ip = nss_ipsec_klips_get_ipsec_ifnum + .cb = nss_ipsec_klips_get_tun_dev }; #endif @@ -2116,11 +2010,7 @@ int __init nss_ipsec_klips_init_module(v ecm_interface_ipsec_register_callbacks(&nss_ipsec_klips_ecm); ecm_notifier_register_connection_notify(&nss_ipsec_klips_ecm_conn_notifier); #if defined(NSS_L2TPV2_ENABLED) - l2tpmgr_register_ipsecmgr_callback_by_netdev(&nss_ipsec_klips_l2tp); -#endif - -#if defined(NSS_VXLAN_ENABLED) - nss_vxlanmgr_register_ipsecmgr_callback_by_ip(&nss_ipsec_klips_vxlan_cb); + l2tpmgr_register_ipsecmgr_callback(&nss_ipsec_klips_l2tp); #endif return 0; } @@ -2142,11 +2032,7 @@ void __exit nss_ipsec_klips_exit_module( ecm_notifier_unregister_connection_notify(&nss_ipsec_klips_ecm_conn_notifier); ecm_interface_ipsec_unregister_callbacks(); #if defined(NSS_L2TPV2_ENABLED) - l2tpmgr_unregister_ipsecmgr_callback_by_netdev(); -#endif - -#if defined(NSS_VXLAN_ENABLED) - nss_vxlanmgr_unregister_ipsecmgr_callback_by_ip(); + l2tpmgr_unregister_ipsecmgr_callback(); #endif nss_cfi_ocf_unregister_ipsec(); --- a/l2tp/l2tpv2/Makefile +++ b/l2tp/l2tpv2/Makefile @@ -1,7 +1,7 @@ # Makefile for l2tp client ccflags-y += -I$(obj)/../../exports -I$(obj)/../.. -I$(obj)/nss_hal/include ccflags-y += -DNSS_L2TP_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror +ccflags-y += -Werror ifneq (,$(filter $(CONFIG_L2TP),m y)) obj-m += qca-nss-l2tpv2.o qca-nss-l2tpv2-objs := nss_connmgr_l2tpv2.o nss_l2tpv2_stats.o --- a/l2tp/l2tpv2/nss_connmgr_l2tpv2.c +++ b/l2tp/l2tpv2/nss_connmgr_l2tpv2.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2015-2017, 2019-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, 2019-2020 The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -100,11 +99,8 @@ static DEFINE_HASHTABLE(l2tpv2_session_data_hash_table, HASH_BUCKET_SIZE); static int ip_ttl_max = 255; - -#if defined(NSS_L2TP_IPSEC_BIND_BY_NETDEV) static char l2tpoipsec_config[L2TP_SYSCTL_STR_LEN_MAX]; static struct ctl_table_header *ctl_tbl_hdr; /* l2tpv2 sysctl */ -#endif static struct l2tpmgr_ipsecmgr_cb __rcu ipsecmgr_cb; /* @@ -248,23 +244,24 @@ static struct nss_connmgr_l2tpv2_session */ data->l2tpv2.session.session_id = session->session_id; data->l2tpv2.session.peer_session_id = session->peer_session_id; + data->l2tpv2.session.offset = 0; data->l2tpv2.session.hdr_len = session->hdr_len; data->l2tpv2.session.reorder_timeout = session->reorder_timeout; data->l2tpv2.session.recv_seq = session->recv_seq; data->l2tpv2.session.send_seq = session->send_seq; - nss_connmgr_l2tpv2_info("sess %u, peer=%u nr=%u ns=%u hdr_len=%u timeout=%x" + nss_connmgr_l2tpv2_info("sess %u, peer=%u nr=%u ns=%u off=%u hdr_len=%u timeout=%x" " recv_seq=%x send_seq=%x\n", session->session_id, session->peer_session_id, session->nr, - session->ns, session->hdr_len, + session->ns, 0, session->hdr_len, session->reorder_timeout, session->recv_seq, session->send_seq); - /* - * tunnel->sock->sk_no_check/sk_no_check_tx is set to true - * if UDP checksum is not needed for the L2TP socket. - */ - data->l2tpv2.tunnel.udp_csum = !tunnel->sock->sk_no_check_tx; +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 16, 0)) + data->l2tpv2.tunnel.udp_csum = tunnel->sock->sk_no_check; +#else + data->l2tpv2.tunnel.udp_csum = tunnel->sock->sk_no_check_tx; +#endif inet = inet_sk(tunnel->sock); @@ -359,6 +356,9 @@ static void nss_connmgr_l2tpv2_exception { const struct iphdr *iph_outer, *iph_inner; struct nss_connmgr_l2tpv2_session_data *ptr; +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 8, 0)) + struct hlist_node *node; +#endif uint16_t *l2tp_hdr; uint16_t l2tp_flags; int l2tp_hdr_len = L2TP_HDR_MIN_LEN; @@ -374,6 +374,9 @@ static void nss_connmgr_l2tpv2_exception rcu_read_lock(); hash_for_each_possible_rcu(l2tpv2_session_data_hash_table, ptr, +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 8, 0)) + node, +#endif hash_list, dev->ifindex) { if (ptr->dev == dev) { tunnel_local_ip = ptr->data.ip.v4.saddr.s_addr; @@ -477,56 +480,6 @@ static void nss_connmgr_l2tpv2_event_rec } /* - * nss_connmgr_l2tpv2_bind_ipsec_by_ipaddr() - * Bind L2TP tunnel with IPsec(xfrm) based on IP Address - */ -static void nss_connmgr_l2tpv2_bind_ipsec_by_ipaddr(struct nss_ctx_instance *nss_ctx, struct nss_connmgr_l2tpv2_data *l2tpv2_data, uint32_t l2tp_ifnum) -{ - struct nss_l2tpv2_msg l2tpv2msg; - nss_tx_status_t status; - struct nss_l2tpv2_bind_ipsec_if_msg *l2tpv2_bind_ipsec_msg; - int32_t ipsec_ifnum = -1; - get_ipsec_ifnum_by_ip_addr_callback_t ipsec_cb; - - /* - * Check if the L2TP interface is applied over an IPsec (XFRM) interface by querying the IPsec - * client by using the L2TP tunnel IPv4 source/destination addresses. - */ - rcu_read_lock(); - ipsec_cb = rcu_dereference(ipsecmgr_cb.get_ifnum_by_ip_addr); - ipsec_ifnum = ipsec_cb ? ipsec_cb(IPVERSION, &l2tpv2_data->ip.v4.saddr.s_addr, &l2tpv2_data->ip.v4.daddr.s_addr) : -1; - rcu_read_unlock(); - - if (ipsec_ifnum < 0) { - nss_connmgr_l2tpv2_info("%px: Invalid IPsec interface no.(0x%x) based on local & remote IP-address\n", nss_ctx, ipsec_ifnum); - return; - } - - /* - * For, l2tpoipsec, send the command to bind the l2tp session with the IPsec interface. - */ - memset(&l2tpv2msg, 0, sizeof(struct nss_l2tpv2_msg)); - nss_l2tpv2_msg_init(&l2tpv2msg, l2tp_ifnum, NSS_L2TPV2_MSG_BIND_IPSEC_IF, - sizeof(struct nss_l2tpv2_bind_ipsec_if_msg), (void *)nss_connmgr_l2tpv2_msg_cb, NULL); - l2tpv2_bind_ipsec_msg = &l2tpv2msg.msg.bind_ipsec_if_msg; - l2tpv2_bind_ipsec_msg->ipsec_ifnum = ipsec_ifnum; - - status = nss_l2tpv2_tx(nss_ctx, &l2tpv2msg); - if (status != NSS_TX_SUCCESS) { - /* - * TODO: Add retry logic. Currently it sends a warning message to user. - * In case of bind fails, then we don't bring down L2TP tunnel, instead we give a warning log - * to user, as this introduces a potential risk of not having a per packet check for source - * interface number in firmware. - */ - nss_connmgr_l2tpv2_warning("%px: L2TPv2 interface binding with IPSec interface(0x%x) failed.\n", nss_ctx, ipsec_ifnum); - return; - } - - nss_connmgr_l2tpv2_info("%px: L2TPv2 interface is bound to IPsec interface with if_num(0x%x)\n", nss_ctx, ipsec_ifnum); -} - -/* * nss_connmgr_l2tpv2_dev_up() * pppol2tpv2 interface's up event handler */ @@ -630,12 +583,7 @@ static int nss_connmgr_l2tpv2_dev_up(str return NOTIFY_BAD; } - nss_connmgr_l2tpv2_info("%px: nss_l2tpv2_tx() CREATE successful\n", nss_ctx); - - /* - * Check if we need to bind the L2TP to an IPsec interface. This is required as per RFC3193 - */ - nss_connmgr_l2tpv2_bind_ipsec_by_ipaddr(nss_ctx, data, if_number); + nss_connmgr_l2tpv2_info("%px: nss_l2tpv2_tx() successful\n", nss_ctx); return NOTIFY_DONE; } @@ -648,6 +596,9 @@ static int nss_connmgr_l2tpv2_dev_down(s { struct nss_connmgr_l2tpv2_session_data *ptr; struct hlist_node *tmp; +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 8, 0)) + struct hlist_node *node; +#endif struct nss_l2tpv2_msg l2tpv2msg; struct nss_l2tpv2_session_destroy_msg *l2tpv2cfg; int if_number; @@ -671,6 +622,9 @@ static int nss_connmgr_l2tpv2_dev_down(s } hash_for_each_possible_safe(l2tpv2_session_data_hash_table, ptr, +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 8, 0)) + node, +#endif tmp, hash_list, dev->ifindex) { if (ptr->dev == dev) { dev_put(dev); @@ -713,7 +667,11 @@ static int nss_connmgr_l2tpv2_dev_event( unsigned long event, void *dev) { struct net_device *netdev; +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 0)) + netdev = (struct net_device *)dev; +#else netdev = netdev_notifier_info_to_dev(dev); +#endif switch (event) { case NETDEV_UP: @@ -736,6 +694,9 @@ static int nss_connmgr_l2tpv2_dev_event( int nss_connmgr_l2tpv2_get_data(struct net_device *dev, struct nss_connmgr_l2tpv2_data *data) { struct nss_connmgr_l2tpv2_session_data *ptr; +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 8, 0)) + struct hlist_node *node; +#endif if (!data) { nss_connmgr_l2tpv2_info("nss_connmgr_l2tpv2_data ptr is null\n"); return -EINVAL; @@ -743,6 +704,9 @@ int nss_connmgr_l2tpv2_get_data(struct n rcu_read_lock(); hash_for_each_possible_rcu(l2tpv2_session_data_hash_table, ptr, +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 8, 0)) + node, +#endif hash_list, dev->ifindex) { if (ptr->dev == dev) { memcpy(data, &ptr->data, sizeof(struct nss_connmgr_l2tpv2_data)); @@ -763,9 +727,15 @@ EXPORT_SYMBOL(nss_connmgr_l2tpv2_get_dat int nss_connmgr_l2tpv2_does_connmgr_track(const struct net_device *dev) { struct nss_connmgr_l2tpv2_session_data *ptr; +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 8, 0)) + struct hlist_node *node; +#endif rcu_read_lock(); hash_for_each_possible_rcu(l2tpv2_session_data_hash_table, ptr, +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 8, 0)) + node, +#endif hash_list, dev->ifindex) { if (ptr->dev == dev) { rcu_read_unlock(); @@ -779,83 +749,6 @@ int nss_connmgr_l2tpv2_does_connmgr_trac EXPORT_SYMBOL(nss_connmgr_l2tpv2_does_connmgr_track); /* - * l2tpmgr_register_ipsecmgr_callback_by_ipaddr() - * Register IPSecmgr callback. - */ -void l2tpmgr_register_ipsecmgr_callback_by_ipaddr(struct l2tpmgr_ipsecmgr_cb *cb) -{ - get_ipsec_ifnum_by_ip_addr_callback_t ipsec_get_ifnum_by_ip_addr; - - rcu_read_lock(); - ipsec_get_ifnum_by_ip_addr = rcu_dereference(ipsecmgr_cb.get_ifnum_by_ip_addr); - if (ipsec_get_ifnum_by_ip_addr) { - rcu_read_unlock(); - nss_connmgr_l2tpv2_info("%px: IPSecmgr Callback get_ifnum_by_ip_addr is already registered\n", cb); - return; - } - rcu_read_unlock(); - - if (cb->get_ifnum_by_ip_addr == NULL) { - nss_connmgr_l2tpv2_warning("%px: IPSecmgr Callback get_ifnum_by_ip_addr is NULL\n", cb); - return; - } - - rcu_assign_pointer(ipsecmgr_cb.get_ifnum_by_ip_addr, cb->get_ifnum_by_ip_addr); - synchronize_rcu(); -} -EXPORT_SYMBOL(l2tpmgr_register_ipsecmgr_callback_by_ipaddr); - -/* - * l2tpmgr_unregister_ipsecmgr_callback_by_ipaddr - * Unregister callback. - */ -void l2tpmgr_unregister_ipsecmgr_callback_by_ipaddr(void) -{ - rcu_assign_pointer(ipsecmgr_cb.get_ifnum_by_ip_addr, NULL); - synchronize_rcu(); -} -EXPORT_SYMBOL(l2tpmgr_unregister_ipsecmgr_callback_by_ipaddr); - -#if defined(NSS_L2TP_IPSEC_BIND_BY_NETDEV) -/* - * l2tpmgr_register_ipsecmgr_callback_by_netdev() - * Register IPSecmgr callback. - */ -void l2tpmgr_register_ipsecmgr_callback_by_netdev(struct l2tpmgr_ipsecmgr_cb *cb) -{ - get_ipsec_ifnum_by_dev_callback_t ipsec_get_ifnum_by_dev; - - rcu_read_lock(); - ipsec_get_ifnum_by_dev = rcu_dereference(ipsecmgr_cb.get_ifnum_by_dev); - if (ipsec_get_ifnum_by_dev) { - rcu_read_unlock(); - nss_connmgr_l2tpv2_info("%px: IPSecmgr Callback get_ifnum_by_dev is already registered\n", cb); - return; - } - rcu_read_unlock(); - - if (cb->get_ifnum_by_dev == NULL) { - nss_connmgr_l2tpv2_warning("%px: IPSecmgr Callback get_ifnum_by_dev is NULL\n", cb); - return; - } - - rcu_assign_pointer(ipsecmgr_cb.get_ifnum_by_dev, cb->get_ifnum_by_dev); - synchronize_rcu(); -} -EXPORT_SYMBOL(l2tpmgr_register_ipsecmgr_callback_by_netdev); - -/* - * l2tpmgr_unregister_ipsecmgr_callback_by_netdev - * Unregister callback. - */ -void l2tpmgr_unregister_ipsecmgr_callback_by_netdev(void) -{ - rcu_assign_pointer(ipsecmgr_cb.get_ifnum_by_dev, NULL); - synchronize_rcu(); -} -EXPORT_SYMBOL(l2tpmgr_unregister_ipsecmgr_callback_by_netdev); - -/* * nss_connmgr_l2tpv2_proc_handler() * Read and write handler for sysctl. */ @@ -866,14 +759,13 @@ static int nss_connmgr_l2tpv2_proc_handl char *l2tp_device_name, *ipsec_device_name; char *input_str = l2tpoipsec_config; int32_t l2tp_ifnum, ipsec_ifnum; - struct net_device *l2tpdev, *ipsecdev; + struct net_device *l2tpdev, *ipsecdev, *ipsectundev; nss_tx_status_t status; struct nss_l2tpv2_msg l2tpv2msg; - get_ipsec_ifnum_by_dev_callback_t ipsec_cb; - struct nss_l2tpv2_bind_ipsec_if_msg *l2tpv2_bind_ipsec_msg; + get_ipsec_tundev_callback_t ipsec_cb; + struct nss_l2tpv2_bind_ipsec_if_msg *l2tpv2_bind_ipsec_if; struct nss_ctx_instance *nss_ctx = nss_l2tpv2_get_context(); int ret = proc_dostring(ctl, write, buffer, lenp, ppos); - struct nss_connmgr_l2tpv2_session_data *ptr; if (!write) { nss_connmgr_l2tpv2_info("command to write is echo > \n"); @@ -900,19 +792,6 @@ static int nss_connmgr_l2tpv2_proc_handl return -EINVAL; } - rcu_read_lock(); - hash_for_each_possible_rcu(l2tpv2_session_data_hash_table, ptr, - hash_list, l2tpdev->ifindex) { - if (ptr->dev != l2tpdev) { - continue; - } - - if (ptr->data.l2tpv2.tunnel.udp_csum) { - nss_connmgr_l2tpv2_info("Enabling UDP checksum in L2TP packet is not supported for l2tpoipsec flow\n"); - } - } - rcu_read_unlock(); - ipsecdev = dev_get_by_name(&init_net, ipsec_device_name); if (!ipsecdev) { nss_connmgr_l2tpv2_info("Cannot find the netdevice associated with %s\n", ipsec_device_name); @@ -931,7 +810,7 @@ static int nss_connmgr_l2tpv2_proc_handl } rcu_read_lock(); - ipsec_cb = rcu_dereference(ipsecmgr_cb.get_ifnum_by_dev); + ipsec_cb = rcu_dereference(ipsecmgr_cb.cb); if (!ipsec_cb) { rcu_read_unlock(); nss_connmgr_l2tpv2_info("Callback to get IPsec tun device not registered"); @@ -940,13 +819,27 @@ static int nss_connmgr_l2tpv2_proc_handl } /* - * Get NSS ifnum for IPsec interface. + * Get the dummy netdevice used to register this IPSec + * device with NSS from the ipsecmgr module. This is + * needed for looking up the NSS ifnum for the IPSec + * netdevice. */ - ipsec_ifnum = ipsec_cb(ipsecdev); + ipsectundev = ipsec_cb(ipsecdev); rcu_read_unlock(); + if (!ipsectundev) { + nss_connmgr_l2tpv2_info("Cannot get the device from IPSecmgr for %s\n", ipsec_device_name); + ret = -ENODEV; + goto exit; + } + + /* + * Get NSS ifnum for IPsec interface. + */ + ipsec_ifnum = nss_cmn_get_interface_number_by_dev_and_type(ipsectundev, NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_INNER); if (ipsec_ifnum == -1) { nss_connmgr_l2tpv2_info("Cannot find the NSS interface associated with %s\n", ipsec_device_name); ret = -ENODEV; + dev_put(ipsectundev); goto exit; } @@ -955,14 +848,15 @@ static int nss_connmgr_l2tpv2_proc_handl */ memset(&l2tpv2msg, 0, sizeof(struct nss_l2tpv2_msg)); nss_l2tpv2_msg_init(&l2tpv2msg, l2tp_ifnum, NSS_L2TPV2_MSG_BIND_IPSEC_IF, sizeof(struct nss_l2tpv2_bind_ipsec_if_msg), (void *)nss_connmgr_l2tpv2_msg_cb, NULL); - l2tpv2_bind_ipsec_msg = &l2tpv2msg.msg.bind_ipsec_if_msg; - l2tpv2_bind_ipsec_msg->ipsec_ifnum = ipsec_ifnum; + l2tpv2_bind_ipsec_if = &l2tpv2msg.msg.bind_ipsec_if_msg; + l2tpv2_bind_ipsec_if->ipsec_ifnum = ipsec_ifnum; status = nss_l2tpv2_tx(nss_ctx, &l2tpv2msg); if (status != NSS_TX_SUCCESS) { nss_connmgr_l2tpv2_info("%px IPSec interface bind failed\n", nss_ctx); ret = -EAGAIN; } + dev_put(ipsectundev); exit: dev_put(l2tpdev); dev_put(ipsecdev); @@ -970,6 +864,38 @@ exit: } /* + * l2tpmgr_register_ipsecmgr_callback() + * Register IPSecmgr callback. + */ +void l2tpmgr_register_ipsecmgr_callback(struct l2tpmgr_ipsecmgr_cb *cb) +{ + get_ipsec_tundev_callback_t ipsec_cb; + rcu_read_lock(); + ipsec_cb = rcu_dereference(ipsecmgr_cb.cb); + if (ipsec_cb) { + rcu_read_unlock(); + nss_connmgr_l2tpv2_info("IPSecmgr Callback is already registered\n"); + return; + } + + rcu_assign_pointer(ipsecmgr_cb.cb, cb->cb); + rcu_read_unlock(); +} +EXPORT_SYMBOL(l2tpmgr_register_ipsecmgr_callback); + +/* + * l2tpmgr_unregister_ipsecmgr_callback + * Unregister callback. + */ +void l2tpmgr_unregister_ipsecmgr_callback(void) +{ + rcu_read_lock(); + rcu_assign_pointer(ipsecmgr_cb.cb, NULL); + rcu_read_unlock(); +} +EXPORT_SYMBOL(l2tpmgr_unregister_ipsecmgr_callback); + +/* * nss_connmgr_l2tpv2_table */ static struct ctl_table nss_connmgr_l2tpv2_table[] = { @@ -1006,7 +932,6 @@ static struct ctl_table nss_connmgr_l2tp }, { } }; -#endif /* * Linux Net device Notifier @@ -1029,20 +954,18 @@ int __init nss_connmgr_l2tpv2_init_modul return 0; } #endif -#if defined(NSS_L2TP_IPSEC_BIND_BY_NETDEV) ctl_tbl_hdr = register_sysctl_table(nss_connmgr_l2tpv2_sysroot); if (!ctl_tbl_hdr) { nss_connmgr_l2tpv2_info("Unable to register sysctl table for L2TP conn mgr\n"); return -EFAULT; } -#endif /* * Initialize ipsecmgr callback. */ - rcu_assign_pointer(ipsecmgr_cb.get_ifnum_by_dev, NULL); - rcu_assign_pointer(ipsecmgr_cb.get_ifnum_by_ip_addr, NULL); - synchronize_rcu(); + rcu_read_lock(); + rcu_assign_pointer(ipsecmgr_cb.cb, NULL); + rcu_read_unlock(); register_netdevice_notifier(&nss_connmgr_l2tpv2_notifier); return 0; } --- a/l2tp/l2tpv2/nss_connmgr_l2tpv2.h +++ b/l2tp/l2tpv2/nss_connmgr_l2tpv2.h @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2015, 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -27,21 +27,13 @@ #include #include #include -#include #define L2TP_V_2 2 -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 12, 0)) -#define tunnel_hold(tunnel) atomic_inc(&tunnel->ref_count) -#define tunnel_put(tunnel) atomic_dec(&tunnel->ref_count) -#define session_hold(session) atomic_inc(&session->ref_count) -#define session_put(session) atomic_dec(&session->ref_count) -#else #define tunnel_hold(tunnel) refcount_inc(&tunnel->ref_count) #define tunnel_put(tunnel) refcount_dec(&tunnel->ref_count) #define session_hold(session) refcount_inc(&session->ref_count) #define session_put(session) refcount_dec(&session->ref_count) -#endif /* * ---------------------------------------------------------------------------------- @@ -54,6 +46,7 @@ */ struct session_info { u32 session_id, peer_session_id; /* local & remote session id */ + u16 offset; /* offset to data */ u16 hdr_len; /* header length */ int reorder_timeout; /* reorder timeout */ unsigned send_seq:1; /* enable tx sequence number ? */ --- a/l2tp/l2tpv2/nss_l2tpv2_stats.c +++ b/l2tp/l2tpv2/nss_l2tpv2_stats.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2015, 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -21,9 +21,7 @@ */ #include -#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) -#include -#endif +#include #include #include #include @@ -94,8 +92,6 @@ void nss_l2tpv2_update_dev_stats(struct dev_hold(dev); - memset(&l2tp_stats, 0, sizeof(struct l2tp_stats)); - /* * Get tunnel id */ @@ -108,35 +104,37 @@ void nss_l2tpv2_update_dev_stats(struct /* * Update tunnel & session stats */ -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 12, 0)) - tunnel = l2tp_tunnel_find(dev_net(dev), data.l2tpv2.tunnel.tunnel_id); + tunnel = l2tp_tunnel_get(dev_net(dev), data.l2tpv2.tunnel.tunnel_id); if (!tunnel) { dev_put(dev); return; } tunnel_hold(tunnel); - session = l2tp_session_find(dev_net(dev), tunnel, data.l2tpv2.session.session_id); + session = l2tp_session_get(dev_net(dev), data.l2tpv2.session.session_id); if (!session) { tunnel_put(tunnel); dev_put(dev); return; } + + memset(&l2tp_stats, 0, sizeof(struct l2tp_stats)); + session_hold(session); -#else - tunnel = l2tp_tunnel_get(dev_net(dev), data.l2tpv2.tunnel.tunnel_id); - if (!tunnel) { - dev_put(dev); - return; - } - session = l2tp_tunnel_get_session(tunnel, data.l2tpv2.session.session_id); - if (!session) { - tunnel_put(tunnel); - dev_put(dev); - return; - } -#endif +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 8, 0)) + /* valid session found. Update stats */ + l2tp_stats.tx_packets = (u64)sync_stats->node_stats.tx_packets; + l2tp_stats.tx_bytes = (u64)sync_stats->node_stats.tx_bytes; + l2tp_stats.tx_errors = (u64)sync_stats->tx_errors; + + l2tp_stats.rx_packets = (u64)sync_stats->node_stats.rx_packets; + l2tp_stats.rx_bytes = (u64)sync_stats->node_stats.rx_bytes; + l2tp_stats.rx_errors = (u64)sync_stats->rx_errors; + + l2tp_stats.rx_seq_discards = (u64)sync_stats->rx_seq_discards; + l2tp_stats.rx_oos_packets = (u64)sync_stats->rx_oos_packets; +#else atomic_long_set(&l2tp_stats.tx_packets, (long)sync_stats->node_stats.tx_packets); atomic_long_set(&l2tp_stats.tx_bytes, (long)sync_stats->node_stats.tx_bytes); atomic_long_set(&l2tp_stats.tx_errors, (long)sync_stats->tx_errors); @@ -148,6 +146,7 @@ void nss_l2tpv2_update_dev_stats(struct atomic_long_set(&l2tp_stats.rx_seq_discards, (long)sync_stats->rx_seq_discards); atomic_long_set(&l2tp_stats.rx_oos_packets, (long)(sync_stats->rx_oos_packets)); +#endif l2tp_stats_update(tunnel, session, &l2tp_stats); session_put(session); --- a/lag/Makefile +++ b/lag/Makefile @@ -7,7 +7,7 @@ endif ccflags-y := -I$(obj) -I$(obj)/.. ccflags-y += -DNSS_CLIENT_BUILD_ID="$(BUILD_ID)" ccflags-y += -DNSS_LAG_MGR_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-lag-mgr.o qca-nss-lag-mgr-objs := nss_lag.o --- a/map/map-t/Makefile +++ b/map/map-t/Makefile @@ -1,7 +1,7 @@ # Makefile for map-t client ccflags-y += -I$(obj)/../../exports -I$(obj)/../.. -I$(obj)/nss_hal/include ccflags-y += -DNSS_MAP_T_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-map-t.o qca-nss-map-t-objs := nss_connmgr_map_t.o --- a/map/map-t/nss_connmgr_map_t.c +++ b/map/map-t/nss_connmgr_map_t.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -424,15 +424,12 @@ static void nss_connmgr_map_t_decap_exce struct ipv6hdr ip6_hdr_r; uint8_t next_hdr, hop_limit, tclass, l4_proto; int total_len; - uint32_t identifier = 0; + uint32_t identifier; bool df_bit = false; uint16_t skip_sz = 0; - struct nss_map_t_mdata *mdata; - mdata = (struct nss_map_t_mdata *)skb->data; - - /* discard meta data header */ - skb_pull(skb, sizeof(struct nss_map_t_mdata)); + /* discard L2 header */ + skb_pull(skb, sizeof(struct ethhdr)); skb_reset_mac_header(skb); skb_reset_network_header(skb); @@ -462,12 +459,7 @@ static void nss_connmgr_map_t_decap_exce tclass = nss_connmgr_map_t_ipv6_get_tclass(ip6_hdr); if (likely(next_hdr != NEXTHDR_FRAGMENT)) { - - /* - * Set DF bit - */ - df_bit = !!(mdata->flags & NSS_MAPT_MDATA_FLAG_DF_BIT); - + df_bit = true; l4_proto = next_hdr; } else { struct frag_hdr tmp_fh, *fh; @@ -504,16 +496,8 @@ static void nss_connmgr_map_t_decap_exce ip4_hdr->tos = tclass; if (unlikely(df_bit)) { ip4_hdr->frag_off = htons(IP_DF); - } - - if (unlikely(identifier)) { - ip4_hdr->id = htons(identifier & 0xffff); } else { - /* - * Generate the new identifier value and set it - * in the IPv4 Identification field. - */ - __ip_select_ident(dev_net(dev), ip4_hdr, 1); + ip4_hdr->id = htons(identifier & 0xffff); } skb->pkt_type = PACKET_HOST; @@ -531,7 +515,7 @@ static void nss_connmgr_map_t_decap_exce /* * nss_connmgr_map_t_encap_exception() * Exception handler registered to NSS for handling map_t ipv4 pkts - * Send the translated ipv4 packets to the stack directly. + * Translates ipv4 packet back to ipv6 and send to nat46 device directly. */ static void nss_connmgr_map_t_encap_exception(struct net_device *dev, struct sk_buff *skb, @@ -539,32 +523,147 @@ static void nss_connmgr_map_t_encap_exce { struct iphdr *ip4_hdr; + struct ipv6hdr *ip6_hdr; + uint8_t v6saddr[16], v6daddr[16]; + struct tcphdr *tcph = NULL; + struct udphdr *udph = NULL; + struct iphdr ip4_hdr_r; + __be16 sport, dport; + uint8_t nexthdr, hop_limit, tos; + int payload_len; + bool df_bit = false; + uint16_t append_hdr_sz = 0; + uint16_t identifier; + uint32_t l4_csum; + uint16_t csum; + /* discard L2 header */ skb_pull(skb, sizeof(struct ethhdr)); skb_reset_mac_header(skb); + skb_reset_network_header(skb); ip4_hdr = ip_hdr(skb); - skb_set_transport_header(skb, ip4_hdr->ihl * 4); + skb_set_transport_header(skb, ip4_hdr->ihl*4); + + if (ip4_hdr->protocol == IPPROTO_TCP) { + tcph = tcp_hdr(skb); + l4_csum = tcph->check; + sport = tcph->source; + dport = tcph->dest; + } else if (ip4_hdr->protocol == IPPROTO_UDP) { + udph = udp_hdr(skb); + l4_csum = udph->check; + sport = udph->source; + dport = udph->dest; + } else { + nss_connmgr_map_t_warning("%px: Unsupported protocol, free it up\n", dev); + dev_kfree_skb_any(skb); + return; + } /* - * IP Header checksum is not generated yet, calculate it now. + * Undo the checksum of the IPv4 source and destinationIPv4 address. */ - ip4_hdr->check = 0; - ip4_hdr->check = ip_fast_csum((unsigned char *)ip4_hdr, ip4_hdr->ihl); + csum = ip_compute_csum(&ip4_hdr->saddr, 2 * sizeof(ip4_hdr->saddr)); + l4_csum += ((~csum) & 0xFFFF); + + /* + * IPv6 packet is xlated to ipv4 packet by acceleration engine. But there is no ipv4 rule. + * Call xlate_4_to_6() [ which is exported by nat46.ko ] to find original ipv6 src and ipv6 dest address. + * These functions is designed for packets from lan to wan. Since this packet is from wan, need to call + * this function with parameters reversed. ipv4_hdr_r is used for reversing ip addresses. + */ + ip4_hdr_r.daddr = ip4_hdr->saddr; + ip4_hdr_r.saddr = ip4_hdr->daddr; + + if (unlikely(!xlate_4_to_6(dev, &ip4_hdr_r, dport, sport, v6saddr, v6daddr))) { /* exception happened after packet got xlated */ + nss_connmgr_map_t_warning("%px: Martian ipv4 packet !!..free it. (saddr = 0x%x daddr = 0x%x sport = %d dport = %d)\n", dev,\ + ip4_hdr->saddr, ip4_hdr->daddr, sport, dport); + dev_kfree_skb_any(skb); + return; + } + + nexthdr = ip4_hdr->protocol; + payload_len = ntohs(ip4_hdr->tot_len) - sizeof(struct iphdr); + hop_limit = ip4_hdr->ttl; + tos = ip4_hdr->tos; + identifier = ntohs(ip4_hdr->id); + + if (ip4_hdr->frag_off & htons(IP_DF)) { + df_bit = true; + } else if (map_t_flags & MAPT_FLAG_ADD_DUMMY_HDR) { + append_hdr_sz = sizeof(struct frag_hdr); + } + + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + append_hdr_sz - sizeof(struct iphdr))) { + nss_connmgr_map_t_warning("%px: Not enough headroom for ipv6 packet...Freeing the packet\n", dev); + dev_kfree_skb_any(skb); + return; + } + + skb_push(skb, sizeof(struct ipv6hdr) + append_hdr_sz - sizeof(struct iphdr)); + skb_reset_network_header(skb); + skb_reset_mac_header(skb); + + skb->protocol = htons(ETH_P_IPV6); + + ip6_hdr = ipv6_hdr(skb); + memset(ip6_hdr, 0, sizeof(struct ipv6hdr)); + + ip6_hdr->version = 6; + ip6_hdr->payload_len = htons(payload_len + append_hdr_sz); + ip6_hdr->hop_limit = hop_limit; + + nss_connmgr_map_t_ipv6_set_tclass(ip6_hdr, tos); + memcpy(&ip6_hdr->daddr, v6saddr, sizeof(struct in6_addr)); + memcpy(&ip6_hdr->saddr, v6daddr, sizeof(struct in6_addr)); + + if (unlikely(df_bit) || !(map_t_flags & MAPT_FLAG_ADD_DUMMY_HDR)) { + ip6_hdr->nexthdr = nexthdr; + } else { + struct frag_hdr tmp_fh, *fh; + const __be32 *fh_addr = skb_header_pointer(skb, sizeof(struct ipv6hdr), sizeof(struct frag_hdr), &tmp_fh); + if (!fh_addr) { + nss_connmgr_map_t_warning("%px: Not able to offset to frag header\n", dev); + dev_kfree_skb_any(skb); + return; + } + fh = (struct frag_hdr *)fh_addr; + memset(fh, 0, sizeof(struct frag_hdr)); + fh->identification = htonl(identifier); + fh->nexthdr = nexthdr; + ip6_hdr->nexthdr = NEXTHDR_FRAGMENT; + } + + skb_set_transport_header(skb, sizeof(struct ipv6hdr) + append_hdr_sz); + + /* + * Add the checksum of the IPv6 source and destination address. + */ + l4_csum += ip_compute_csum(ip6_hdr->saddr.s6_addr16, 2 * sizeof(ip6_hdr->saddr)); + + /* + * Fold the 32 bits checksum to 16 bits + */ + l4_csum = (l4_csum & 0x0000FFFF) + (l4_csum >> 16); + l4_csum = (l4_csum & 0x0000FFFF) + (l4_csum >> 16); + + if (nexthdr == IPPROTO_TCP) { + tcph->check = (uint16_t)l4_csum; + } else { + udph->check = (uint16_t)l4_csum; + } - skb->protocol = htons(ETH_P_IP); skb->pkt_type = PACKET_HOST; skb->skb_iif = dev->ifindex; skb->ip_summed = CHECKSUM_NONE; skb->dev = dev; - nss_connmgr_map_t_trace("%px: ipv4 packet exceptioned after v6/v4xlat src=%pI4 dest=%pI4 proto=%d\n", - dev, &ip4_hdr->saddr, &ip4_hdr->daddr, ip4_hdr->protocol); - /* - * Go through Linux network stack. - */ - netif_receive_skb(skb); + nss_connmgr_map_t_trace("%px: ipv4 packet exceptioned after v6 ---> v4 xlate, created original ipv6 packet\n", dev); + nss_connmgr_map_t_trace("%p: Calculted ipv6 params: src_addr=%pI6, dest_addr=%pI6, payload_len=%d, checksum=%x\n", dev, v6saddr, v6daddr, payload_len, l4_csum); + + dev_queue_xmit(skb); return; } --- a/match/nss_match_priv.h +++ b/match/nss_match_priv.h @@ -29,19 +29,19 @@ /* * Statically compile messages at different levels */ -#if (NSS_match_DEBUG_LEVEL < 2) +#if (NSS_MATCH_DEBUG_LEVEL < 2) #define nss_match_warn(s, ...) #else #define nss_match_warn(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) #endif -#if (NSS_match_DEBUG_LEVEL < 3) +#if (NSS_MATCH_DEBUG_LEVEL < 3) #define nss_match_info(s, ...) #else #define nss_match_info(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) #endif -#if (NSS_match_DEBUG_LEVEL < 4) +#if (NSS_MATCH_DEBUG_LEVEL < 4) #define nss_match_trace(s, ...) #else #define nss_match_trace(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) --- a/mirror/Makefile +++ b/mirror/Makefile @@ -2,7 +2,7 @@ ccflags-y += $(NSS_CCFLAGS) -I$(obj)/../../exports ccflags-y += -DNSS_MIRROR_DEBUG_LEVEL=2 -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-mirror.o qca-nss-mirror-objs := \ --- a/mirror/nss_mirror.c +++ b/mirror/nss_mirror.c @@ -1,6 +1,6 @@ /* *************************************************************************** - * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2020, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -180,28 +180,6 @@ static struct rtnl_link_stats64 *nss_mir return stats; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) -/* - * nss_mirror_netdev_stats64() - * Netdev ops function to retrieve stats for kernel version < 4.6 - */ -static struct rtnl_link_stats64 *nss_mirror_netdev_stats64(struct net_device *dev, - struct rtnl_link_stats64 *tot) -{ - return nss_mirror_get_stats(dev, tot); -} -#else -/* - * nss_mirror_netdev_stats64() - * Netdev ops function to retrieve stats - */ -static void nss_mirror_netdev_stats64(struct net_device *dev, - struct rtnl_link_stats64 *tot) -{ - nss_mirror_get_stats(dev, tot); -} -#endif - /* * nss_mirror_netdev_ops * Mirror net device operations. @@ -209,7 +187,7 @@ static void nss_mirror_netdev_stats64(st static const struct net_device_ops nss_mirror_netdev_ops = { .ndo_open = nss_mirror_netdev_up, .ndo_stop = nss_mirror_netdev_down, - .ndo_get_stats64 = nss_mirror_netdev_stats64, + .ndo_get_stats64 = nss_mirror_get_stats, }; /* @@ -300,6 +278,10 @@ static void nss_mirror_data_cb(struct ne return; } + nss_mirror_info("Printing 64 bytes of data\n"); + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1, + skb->data, 64, 0); + dev_hold(netdev); /* --- a/mscs/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# Makefile for mscs client -ccflags-y += -I$(obj)/../exports -I$(obj)/.. -ccflags-y += -DNSS_CLIENT_BUILD_ID="$(BUILD_ID)" -ccflags-y += -DNSS_MSCS_DEBUG_LEVEL=2 -ccflags-y += -Wall -Werror -obj-m += qca-nss-mscs.o -qca-nss-mscs-objs := nss_mscs.o --- a/mscs/nss_mscs.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - ************************************************************************** - * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all copies. - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ************************************************************************** - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_DYNAMIC_DEBUG) - -/* - * Compile messakes for dynamic enable/disable - */ -#define nss_mscs_warning(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) -#define nss_mscs_info(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) -#define nss_mscs_trace(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) -#else - -/* - * Statically compile messages at different levels - */ -#if (NSS_MSCS_DEBUG_LEVEL < 2) -#define nss_mscs_warning(s, ...) -#else -#define nss_mscs_warning(s, ...) pr_warn("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) -#endif - -#if (NSS_MSCS_DEBUG_LEVEL < 3) -#define nss_mscs_info(s, ...) -#else -#define nss_mscs_info(s, ...) pr_notice("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) -#endif - -#if (NSS_MSCS_DEBUG_LEVEL < 4) -#define nss_mscs_trace(s, ...) -#else -#define nss_mscs_trace(s, ...) pr_info("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) -#endif -#endif - -/* - * nss_mscs_ecm - * Register MSCS client callback with ECM MSCS classifier to support MSCS wifi peer lookup. - */ -static struct ecm_classifier_mscs_callbacks nss_mscs_ecm = { - .get_peer_priority = qca_mscs_peer_lookup_n_get_priority, - .update_skb_priority = qca_scs_peer_lookup_n_rule_match, -}; - -/* - * nss_emesh_ecm - * Register EMESH client callback with ECM EMSH-SAWF classifier to update peer mesh latency parameters. - */ -static struct ecm_classifier_emesh_sawf_callbacks nss_emesh_ecm = { - .update_peer_mesh_latency_params = qca_mesh_latency_update_peer_parameter, -}; - -/* - * nss_mscs_init_module() - * MSCS clinet module init function - */ -int __init nss_mscs_init_module(void) -{ -#ifdef CONFIG_OF - /* - * If the node is not compatible, don't do anything. - */ - if (!of_find_node_by_name(NULL, "nss-common")) { - return 0; - } -#endif - - /* - * MSCS is enabled only on supported platform - */ - if (!nss_cmn_get_nss_enabled()) { - nss_mscs_warning("MSCS client is not compatible with this Platform\n"); - return -1; - } - - if (ecm_classifier_mscs_callback_register(&nss_mscs_ecm)) { - nss_mscs_warning("ecm mscs classifier callback registration failed.\n"); - return -1; - } - - if (ecm_classifier_emesh_latency_config_callback_register(&nss_emesh_ecm)) { - ecm_classifier_mscs_callback_unregister(); - nss_mscs_warning("ecm mesh classifier callback registration failed.\n"); - return -1; - } - - nss_mscs_info("NSS MSCS Client loaded: %s\n", NSS_CLIENT_BUILD_ID); - return 0; - -} - -/* - * nss_mscs_exit_module() - * MSCS module exit function - */ -void __exit nss_mscs_exit_module(void) -{ -#ifdef CONFIG_OF - - /* - * If the node is not compatible, don't do anything. - */ - if (!of_find_node_by_name(NULL, "nss-common")) { - return; - } -#endif - - ecm_classifier_mscs_callback_unregister(); - ecm_classifier_emesh_latency_config_callback_unregister(); - nss_mscs_info("MSCS Client unloaded\n"); - -} - -module_init(nss_mscs_init_module); -module_exit(nss_mscs_exit_module); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("NSS MSCS client module"); --- a/netlink/Makefile +++ b/netlink/Makefile @@ -1,8 +1,9 @@ +GRE_ENABLED := $(strip $(if $(filter $(gre), y), 1 , 0)) CAPWAP_ENABLED := $(strip $(if $(filter $(capwapmgr), y), 1 , 0)) -IPSEC_ENABLED := $(strip $(if $(filter $(ipsecmgr), y), 1 , 0)) +IPSEC_ENABLED := 0 DTLS_ENABLED := $(strip $(if $(filter $(dtlsmgr), y), 1 , 0)) -ccflags-y := -Wall -Werror +ccflags-y := -Werror ccflags-y += -I$(obj)/include ccflags-y += -I$(obj)/../exports ccflags-y += -DNSS_NL_DEBUG_LEVEL=4 @@ -10,48 +11,39 @@ ccflags-y += -DNSS_CLIENT_BUILD_ID="$(BU ccflags-y += -DCONFIG_NSS_NLIPV4=1 ccflags-y += -DCONFIG_NSS_NLIPV6=1 -ccflags-y += -DCONFIG_NSS_NLOAM=1 -ccflags-y += -DCONFIG_NSS_NLGRE_REDIR_FAMILY=1 +ccflags-y += -DCONFIG_NSS_NLOAM=0 +ccflags-y += -DCONFIG_NSS_NLGRE_REDIR_FAMILY=${GRE_ENABLED} ccflags-y += -DCONFIG_NSS_NLETHRX=1 ccflags-y += -DCONFIG_NSS_NLDYNAMIC_INTERFACE=1 ccflags-y += -DCONFIG_NSS_NLN2H=1 -ccflags-y += -DCONFIG_NSS_NLIPV4_REASM=1 -ccflags-y += -DCONFIG_NSS_NLIPV6_REASM=1 +ccflags-y += -DCONFIG_NSS_NLIPV4_REASM=0 +ccflags-y += -DCONFIG_NSS_NLIPV6_REASM=0 ccflags-y += -DCONFIG_NSS_NLWIFILI=1 ccflags-y += -DCONFIG_NSS_NLLSO_RX=1 -ccflags-y += -DCONFIG_NSS_NLMAP_T=1 -ccflags-y += -DCONFIG_NSS_NLPPPOE=1 -ccflags-y += -DCONFIG_NSS_NLL2TPV2=1 -ccflags-y += -DCONFIG_NSS_NLQRFS=1 -ccflags-y += -DCONFIG_NSS_NLPPTP=1 +ccflags-y += -DCONFIG_NSS_NLMAP_T=0 +ccflags-y += -DCONFIG_NSS_NLPPPOE=0 +ccflags-y += -DCONFIG_NSS_NLL2TPV2=0 +ccflags-y += -DCONFIG_NSS_NLPPTP=0 ccflags-y += -DCONFIG_NSS_NLCAPWAP=${CAPWAP_ENABLED} ccflags-y += -DCONFIG_NSS_NLIPSEC=${IPSEC_ENABLED} ccflags-y += -DCONFIG_NSS_NLDTLS=${DTLS_ENABLED} -ccflags-y += -DCONFIG_NSS_NLUDP_ST=1 qca-nss-netlink-objs := nss_nl.o -qca-nss-netlink-objs += nss_nlgre_redir_family.o -qca-nss-netlink-objs += nss_nlgre_redir_cmd.o -qca-nss-netlink-objs += nss_nlgre_redir_cmn.o -qca-nss-netlink-objs += nss_nlgre_redir.o -qca-nss-netlink-objs += nss_nlgre_redir_lag.o qca-nss-netlink-objs += nss_nlipv4.o qca-nss-netlink-objs += nss_nlipv6.o -qca-nss-netlink-objs += nss_nloam.o +# qca-nss-netlink-objs += nss_nloam.o qca-nss-netlink-objs += nss_nlethrx.o qca-nss-netlink-objs += nss_nldynamic_interface.o qca-nss-netlink-objs += nss_nln2h.o -qca-nss-netlink-objs += nss_nlipv4_reasm.o -qca-nss-netlink-objs += nss_nlipv6_reasm.o +# qca-nss-netlink-objs += nss_nlipv4_reasm.o +# qca-nss-netlink-objs += nss_nlipv6_reasm.o qca-nss-netlink-objs += nss_nlwifili.o qca-nss-netlink-objs += nss_nllso_rx.o -qca-nss-netlink-objs += nss_nlmap_t.o -qca-nss-netlink-objs += nss_nlpppoe.o -qca-nss-netlink-objs += nss_nll2tpv2.o -qca-nss-netlink-objs += nss_nlpptp.o -qca-nss-netlink-objs += nss_nludp_st.o -qca-nss-netlink-objs += nss_nlqrfs.o - +# qca-nss-netlink-objs += nss_nlmap_t.o +# qca-nss-netlink-objs += nss_nlpppoe.o +# qca-nss-netlink-objs += nss_nll2tpv2.o +# qca-nss-netlink-objs += nss_nlpptp.o +# ifneq (,$(filter $(capwapmgr), y)) qca-nss-netlink-objs += nss_nlcapwap.o endif @@ -60,8 +52,12 @@ ifneq (,$(filter $(dtlsmgr), y)) qca-nss-netlink-objs += nss_nldtls.o endif -ifneq (,$(filter $(ipsecmgr), y)) -qca-nss-netlink-objs += nss_nlipsec.o +ifneq (,$(filter $(gre), y)) +qca-nss-netlink-objs += nss_nlgre_redir_family.o +qca-nss-netlink-objs += nss_nlgre_redir_cmd.o +qca-nss-netlink-objs += nss_nlgre_redir_cmn.o +qca-nss-netlink-objs += nss_nlgre_redir.o +qca-nss-netlink-objs += nss_nlgre_redir_lag.o endif ifeq ($(SoC),$(filter $(SoC),ipq807x ipq807x_64)) --- a/netlink/nss_nl.c +++ b/netlink/nss_nl.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2015-2016,2018-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016,2018-2020 The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -35,8 +35,6 @@ #include "nss_nlcmn_if.h" #include "nss_nldtls.h" #include "nss_nldtls_if.h" -#include "nss_nlgre_redir_if.h" -#include "nss_nlgre_redir_family.h" #include "nss_nlipsec.h" #include "nss_nlipsec_if.h" #include "nss_nlipv4.h" @@ -59,10 +57,6 @@ #include "nss_nlc2c_tx_if.h" #include "nss_nlc2c_rx.h" #include "nss_nlc2c_rx_if.h" -#include "nss_nlipv4_reasm.h" -#include "nss_nlipv4_reasm_if.h" -#include "nss_nlipv6_reasm.h" -#include "nss_nlipv6_reasm_if.h" #include "nss_nlwifili.h" #include "nss_nlwifili_if.h" #include "nss_nllso_rx.h" @@ -75,10 +69,6 @@ #include "nss_nll2tpv2_if.h" #include "nss_nlpptp.h" #include "nss_nlpptp_if.h" -#include "nss_nludp_st.h" -#include "nss_nludp_st_if.h" -#include "nss_nlqrfs.h" -#include "nss_nlqrfs_if.h" /* * nss_nl.c @@ -110,24 +100,6 @@ static struct nss_nl_family family_handl }, { /* - * NSS_NLIPSEC - */ - .name = NSS_NLIPSEC_FAMILY, /* ipsec */ - .entry = NSS_NLIPSEC_INIT, /* init */ - .exit = NSS_NLIPSEC_EXIT, /* exit */ - .valid = CONFIG_NSS_NLIPSEC /* 1 or 0 */ - }, - { - /* - * NSS_NLOAM - */ - .name = NSS_NLOAM_FAMILY, /* oam */ - .entry = NSS_NLOAM_INIT, /* init */ - .exit = NSS_NLOAM_EXIT, /* exit */ - .valid = CONFIG_NSS_NLOAM /* 1 or 0 */ - }, - { - /* * NSS_NLIPV6 */ .name = NSS_NLIPV6_FAMILY, /* ipv6 */ @@ -137,24 +109,6 @@ static struct nss_nl_family family_handl }, { /* - * NSS_NLGRE_REDIR - */ - .name = NSS_NLGRE_REDIR_FAMILY, /* gre_redir */ - .entry = NSS_NLGRE_REDIR_FAMILY_INIT, /* init */ - .exit = NSS_NLGRE_REDIR_FAMILY_EXIT, /* exit */ - .valid = CONFIG_NSS_NLGRE_REDIR_FAMILY /* 1 or 0 */ - }, - { - /* - * NSS_NLCAPWAP - */ - .name = NSS_NLCAPWAP_FAMILY, /* capwap */ - .entry = NSS_NLCAPWAP_INIT, /* init */ - .exit = NSS_NLCAPWAP_EXIT, /* exit */ - .valid = CONFIG_NSS_NLCAPWAP /* 1 or 0 */ - }, - { - /* * NSS_NLDTLS */ .name = NSS_NLDTLS_FAMILY, /* dtls */ @@ -173,15 +127,6 @@ static struct nss_nl_family family_handl }, { /* - * NSS_NLEDMA - */ - .name = NSS_NLEDMA_FAMILY, /* edma */ - .entry = NSS_NLEDMA_INIT, /* init */ - .exit = NSS_NLEDMA_EXIT, /* exit */ - .valid = CONFIG_NSS_NLEDMA /* 1 or 0 */ - }, - { - /* * NSS_NLDYNAMIC_INTERFACE */ .name = NSS_NLDYNAMIC_INTERFACE_FAMILY, /* dynamic interface */ @@ -200,42 +145,6 @@ static struct nss_nl_family family_handl }, { /* - * NSS_NLC2C_TX - */ - .name = NSS_NLC2C_TX_FAMILY, /* c2c_tx */ - .entry = NSS_NLC2C_TX_INIT, /* init */ - .exit = NSS_NLC2C_TX_EXIT, /* exit */ - .valid = CONFIG_NSS_NLC2C_TX /* 1 or 0 */ - }, - { - /* - * NSS_NLC2C_RX - */ - .name = NSS_NLC2C_RX_FAMILY, /* c2c_rx */ - .entry = NSS_NLC2C_RX_INIT, /* init */ - .exit = NSS_NLC2C_RX_EXIT, /* exit */ - .valid = CONFIG_NSS_NLC2C_RX /* 1 or 0 */ - }, - { - /* - * NSS_NLIPV4_REASM - */ - .name = NSS_NLIPV4_REASM_FAMILY, /* ipv4_reasm */ - .entry = NSS_NLIPV4_REASM_INIT, /* init */ - .exit = NSS_NLIPV4_REASM_EXIT, /* exit */ - .valid = CONFIG_NSS_NLIPV4_REASM /* 1 or 0 */ - }, - { - /* - * NSS_NLIPV6_REASM - */ - .name = NSS_NLIPV6_REASM_FAMILY, /* ipv6_reasm */ - .entry = NSS_NLIPV6_REASM_INIT, /* init */ - .exit = NSS_NLIPV6_REASM_EXIT, /* exit */ - .valid = CONFIG_NSS_NLIPV6_REASM /* 1 or 0 */ - }, - { - /* * NSS_NLWIFILI */ .name = NSS_NLWIFILI_FAMILY, /* wifili */ @@ -252,62 +161,6 @@ static struct nss_nl_family family_handl .exit = NSS_NLLSO_RX_EXIT, /* exit */ .valid = CONFIG_NSS_NLLSO_RX /* 1 or 0 */ }, - { - /* - * NSS_NLMAP_T - */ - .name = NSS_NLMAP_T_FAMILY, /* map_t */ - .entry = NSS_NLMAP_T_INIT, /* init */ - .exit = NSS_NLMAP_T_EXIT, /* exit */ - .valid = CONFIG_NSS_NLMAP_T /* 1 or 0 */ - }, - { - /* - * NSS_NLPPPOE - */ - .name = NSS_NLPPPOE_FAMILY, /* pppoe */ - .entry = NSS_NLPPPOE_INIT, /* init */ - .exit = NSS_NLPPPOE_EXIT, /* exit */ - .valid = CONFIG_NSS_NLPPPOE /* 1 or 0 */ - }, - { - /* - * NSS_NLL2TPV2 - */ - .name = NSS_NLL2TPV2_FAMILY, /* l2tpv2 */ - .entry = NSS_NLL2TPV2_INIT, /* init */ - .exit = NSS_NLL2TPV2_EXIT, /* exit */ - .valid = CONFIG_NSS_NLL2TPV2 /* 1 or 0 */ - }, - { - /* - * NSS_NLPPTP - */ - .name = NSS_NLPPTP_FAMILY, /* pptp */ - .entry = NSS_NLPPTP_INIT, /* init */ - .exit = NSS_NLPPTP_EXIT, /* exit */ - .valid = CONFIG_NSS_NLPPTP /* 1 or 0 */ - }, - { - /* - * NSS_NLUDP_ST - */ - .name = NSS_NLUDP_ST_FAMILY, /* udp_st */ - .entry = NSS_NLUDP_ST_INIT, /* init */ - .exit = NSS_NLUDP_ST_EXIT, /* exit */ - .valid = CONFIG_NSS_NLUDP_ST /* 1 or 0 */ - }, - { - /* - * NSS_NLQRFS - */ - .name = NSS_NLQRFS_FAMILY, /* qrfs */ - .entry = NSS_NLQRFS_INIT, /* init */ - .exit = NSS_NLQRFS_EXIT, /* exit */ - .valid = CONFIG_NSS_NLQRFS /* 1 or 0 */ - }, - - }; #define NSS_NL_FAMILY_HANDLER_SZ ARRAY_SIZE(family_handlers) --- a/netlink/nss_nl.h +++ b/netlink/nss_nl.h @@ -25,6 +25,7 @@ #define NSS_NL_DEBUG_LVL_WARN 2 #define NSS_NL_DEBUG_LVL_INFO 3 #define NSS_NL_DEBUG_LVL_TRACE 4 +#define GENL_ID_GENERATE 0 #if defined(CONFIG_DYNAMIC_DEBUG) --- a/netlink/nss_nlcapwap.c +++ b/netlink/nss_nlcapwap.c @@ -1,12 +1,9 @@ /* ************************************************************************** * Copyright (c) 2015-2016,2018-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. - * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. - * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -39,7 +36,6 @@ #include #include #include -#include "nss_crypto_defines.h" #include "nss_nl.h" #include "nss_nlcapwap_if.h" #include "nss_nlcapwap.h" @@ -162,17 +158,6 @@ struct nss_nlcapwap_hdr { */ static struct nss_nlcapwap_global_ctx global_ctx; -static int nss_nlcapwap_ops_create_tun(struct sk_buff *skb, struct genl_info *info); -static int nss_nlcapwap_ops_destroy_tun(struct sk_buff *skb, struct genl_info *info); -static int nss_nlcapwap_ops_update_mtu(struct sk_buff *skb, struct genl_info *info); -static int nss_nlcapwap_ops_dtls(struct sk_buff *skb, struct genl_info *info); -static int nss_nlcapwap_ops_perf(struct sk_buff *skb, struct genl_info *info); -static int nss_nlcapwap_ops_tx_packets(struct sk_buff *skb, struct genl_info *info); -static int nss_nlcapwap_ops_meta_header(struct sk_buff *skb, struct genl_info *info); -static int nss_nlcapwap_ops_ip_flow(struct sk_buff *skb, struct genl_info *info); -static int nss_nlcapwap_ops_keepalive(struct sk_buff *skb, struct genl_info *info); -static int nss_nlcapwap_ops_get_stats(struct sk_buff *skb, struct genl_info *info); - /* * nss_nlcapwap_family_mcgrp * Multicast group for sending message status & events @@ -182,30 +167,11 @@ static const struct genl_multicast_group }; /* - * nss_nlcapwap_cmd_ops - * Operation table called by the generic netlink layer based on the command - */ -struct genl_ops nss_nlcapwap_cmd_ops[] = { - {.cmd = NSS_NLCAPWAP_CMD_TYPE_CREATE_TUN, .doit = nss_nlcapwap_ops_create_tun,}, - {.cmd = NSS_NLCAPWAP_CMD_TYPE_DESTROY_TUN, .doit = nss_nlcapwap_ops_destroy_tun,}, - {.cmd = NSS_NLCAPWAP_CMD_TYPE_UPDATE_MTU, .doit = nss_nlcapwap_ops_update_mtu,}, - {.cmd = NSS_NLCAPWAP_CMD_TYPE_DTLS, .doit = nss_nlcapwap_ops_dtls,}, - {.cmd = NSS_NLCAPWAP_CMD_TYPE_PERF, .doit = nss_nlcapwap_ops_perf,}, - {.cmd = NSS_NLCAPWAP_CMD_TYPE_TX_PACKETS, .doit = nss_nlcapwap_ops_tx_packets,}, - {.cmd = NSS_NLCAPWAP_CMD_TYPE_META_HEADER, .doit = nss_nlcapwap_ops_meta_header,}, - {.cmd = NSS_NLCAPWAP_CMD_TYPE_IP_FLOW, .doit = nss_nlcapwap_ops_ip_flow,}, - {.cmd = NSS_NLCAPWAP_CMD_TYPE_KEEPALIVE, .doit = nss_nlcapwap_ops_keepalive,}, - {.cmd = NSS_STATS_EVENT_NOTIFY, .doit = nss_nlcapwap_ops_get_stats,}, -}; - -/* * nss_nlcapwap_family * Capwap family definition */ struct genl_family nss_nlcapwap_family = { -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 9, 0)) .id = GENL_ID_GENERATE, /* Auto generate ID */ -#endif .name = NSS_NLCAPWAP_FAMILY, /* family name string */ .hdrsize = sizeof(struct nss_nlcapwap_rule), /* NSS NETLINK capwap rule */ .version = NSS_NL_VER, /* Set it to NSS_NL_VER version */ @@ -213,10 +179,6 @@ struct genl_family nss_nlcapwap_family = .netnsok = true, .pre_doit = NULL, .post_doit = NULL, - .ops = nss_nlcapwap_cmd_ops, - .n_ops = ARRAY_SIZE(nss_nlcapwap_cmd_ops), - .mcgrps = nss_nlcapwap_family_mcgrp, - .n_mcgrps = ARRAY_SIZE(nss_nlcapwap_family_mcgrp) }; /* @@ -601,7 +563,6 @@ static void nss_nlcapwap_create_tun_ipv4 } capwap_rule->enabled_features = features; - capwap_rule->outer_sgt_value = nl_rule->msg.create.rule.outer_sgt_value; /* * Configure IPv4 rule @@ -1471,6 +1432,23 @@ static const struct file_operations nss_ }; /* + * nss_nlcapwap_cmd_ops + * Operation table called by the generic netlink layer based on the command + */ +struct genl_ops nss_nlcapwap_cmd_ops[] = { + {.cmd = NSS_NLCAPWAP_CMD_TYPE_CREATE_TUN, .doit = nss_nlcapwap_ops_create_tun,}, + {.cmd = NSS_NLCAPWAP_CMD_TYPE_DESTROY_TUN, .doit = nss_nlcapwap_ops_destroy_tun,}, + {.cmd = NSS_NLCAPWAP_CMD_TYPE_UPDATE_MTU, .doit = nss_nlcapwap_ops_update_mtu,}, + {.cmd = NSS_NLCAPWAP_CMD_TYPE_DTLS, .doit = nss_nlcapwap_ops_dtls,}, + {.cmd = NSS_NLCAPWAP_CMD_TYPE_PERF, .doit = nss_nlcapwap_ops_perf,}, + {.cmd = NSS_NLCAPWAP_CMD_TYPE_TX_PACKETS, .doit = nss_nlcapwap_ops_tx_packets,}, + {.cmd = NSS_NLCAPWAP_CMD_TYPE_META_HEADER, .doit = nss_nlcapwap_ops_meta_header,}, + {.cmd = NSS_NLCAPWAP_CMD_TYPE_IP_FLOW, .doit = nss_nlcapwap_ops_ip_flow,}, + {.cmd = NSS_NLCAPWAP_CMD_TYPE_KEEPALIVE, .doit = nss_nlcapwap_ops_keepalive,}, + {.cmd = NSS_STATS_EVENT_NOTIFY, .doit = nss_nlcapwap_ops_get_stats,}, +}; + +/* * nss_nlcapwap_get_ifnum() * Get the interface number corresponding to netdev */ --- a/netlink/nss_nldtls.c +++ b/netlink/nss_nldtls.c @@ -1,12 +1,9 @@ /* ************************************************************************** - * Copyright (c) 2015-2016,2018-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. - * + * Copyright (c) 2015-2016,2018-2020 The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. - * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -449,7 +446,7 @@ static void nss_nldtls_data_callback(voi * nss_nldtls_create_session() * Create a DTLS session through dtlsmgr driver API. */ -static struct net_device *nss_nldtls_create_session(struct nss_nldtls_rule *nl_rule) +static struct net_device *nss_nldtls_create_session(struct nss_nldtls_rule *nl_rule, uint32_t flags) { struct nss_nldtls_tun_ctx *dtls_tun_data; struct nss_dtlsmgr_config dcfg; @@ -466,7 +463,7 @@ static struct net_device *nss_nldtls_cre memset(&dcfg, 0, sizeof(struct nss_dtlsmgr_config)); algo = nl_rule->msg.create.encap.cfg.crypto.algo; - dcfg.flags = nl_rule->msg.create.flags | NSS_DTLSMGR_ENCAP_METADATA; + dcfg.flags = flags | (NSS_DTLSMGR_ENCAP_METADATA | NSS_DTLSMGR_HDR_CAPWAP); if (algo == NSS_DTLSMGR_ALGO_AES_GCM) dcfg.flags |= NSS_DTLSMGR_CIPHER_MODE_GCM; @@ -608,11 +605,7 @@ static int nss_nldtls_create_ipv4_rule_e ipv4.dest_port = nl_rule->msg.create.encap.cfg.sport; ipv4.dest_port_xlate = nl_rule->msg.create.encap.cfg.sport; - if (nl_rule->msg.create.flags & NSS_DTLSMGR_HDR_UDPLITE) - ipv4.protocol = IPPROTO_UDPLITE; - else - ipv4.protocol = IPPROTO_UDP; - + ipv4.protocol = IPPROTO_UDP; ipv4.in_vlan_tag[0] = NSS_NLDTLS_VLAN_INVALID; ipv4.out_vlan_tag[0] = NSS_NLDTLS_VLAN_INVALID; ipv4.in_vlan_tag[1] = NSS_NLDTLS_VLAN_INVALID; @@ -620,8 +613,6 @@ static int nss_nldtls_create_ipv4_rule_e memcpy(&ipv4.src_mac[0], &nl_rule->msg.create.gmac_ifmac[0], sizeof(ipv4.src_mac)); - dev_put(ndev); - /* * Create an ipv4 rule entry */ @@ -663,11 +654,7 @@ static int nss_nldtls_create_ipv6_rule_e */ memcpy(ipv6.src_ip, nl_rule->msg.create.encap.cfg.dip, sizeof(ipv6.src_ip)); memcpy(ipv6.dest_ip, nl_rule->msg.create.encap.cfg.sip, sizeof(ipv6.dest_ip)); - - if (nl_rule->msg.create.flags & NSS_DTLSMGR_HDR_UDPLITE) - ipv6.protocol = IPPROTO_UDPLITE; - else - ipv6.protocol = IPPROTO_UDP; + ipv6.protocol = IPPROTO_UDP; ipv6.in_vlan_tag[0] = NSS_NLDTLS_VLAN_INVALID; ipv6.in_vlan_tag[1] = NSS_NLDTLS_VLAN_INVALID; @@ -676,8 +663,6 @@ static int nss_nldtls_create_ipv6_rule_e memcpy(&ipv6.src_mac[0], &nl_rule->msg.create.gmac_ifmac[0], sizeof(ipv6.src_mac)); - dev_put(ndev); - /* * Create an ipv6 rule entry */ @@ -744,7 +729,7 @@ static int nss_nldtls_ops_create_tun(str * Create tunnel based on ip version */ if (nl_rule->msg.create.ip_version == NSS_NLDTLS_IP_VERS_4) { - dtls_dev = nss_nldtls_create_session(nl_rule); + dtls_dev = nss_nldtls_create_session(nl_rule, NSS_NLDTLS_IPV4_SESSION); if (!dtls_dev) { nss_nl_error("%px: Unable to create dtls session for v4\n", skb); return -EINVAL; @@ -763,7 +748,7 @@ static int nss_nldtls_ops_create_tun(str atomic_inc(&gbl_ctx.num_tun); nss_nl_info("%px: Successfully created ipv4 dtls tunnel\n", skb); } else { - dtls_dev = nss_nldtls_create_session(nl_rule); + dtls_dev = nss_nldtls_create_session(nl_rule, NSS_DTLSMGR_HDR_IPV6); if (!dtls_dev) { nss_nl_error("%px: Unable to create dtls session for v6\n", skb); return -EINVAL; @@ -886,7 +871,6 @@ static int nss_nldtls_ops_update_config( key_len = nl_rule->msg.update_config.config_update.crypto.cipher_key.len; if (key_len > NSS_NLDTLS_CIPHER_KEY_MAX) { nss_nl_error("Invalid cipher length: %u\n", key_len); - dev_put(dev); return -EINVAL; } @@ -894,7 +878,6 @@ static int nss_nldtls_ops_update_config( key_len = nl_rule->msg.update_config.config_update.crypto.auth_key.len; if (key_len > NSS_NLDTLS_AUTH_KEY_MAX) { nss_nl_error("Invalid authentication length: %u\n", key_len); - dev_put(dev); return -EINVAL; } @@ -902,7 +885,6 @@ static int nss_nldtls_ops_update_config( key_len = nl_rule->msg.update_config.config_update.crypto.nonce.len; if (key_len > NSS_NLDTLS_NONCE_SIZE_MAX) { nss_nl_error("Invalid nonce length: %u\n", key_len); - dev_put(dev); return -EINVAL; } --- a/netlink/nss_nlgre_redir_cmn.c +++ b/netlink/nss_nlgre_redir_cmn.c @@ -1,6 +1,6 @@ /* *************************************************************************** - * Copyright (c) 2015-2016, 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016,2018-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -325,7 +325,7 @@ static struct rtnl_link_stats64 *nss_nlg int i; for (i = 0; i < NSS_GRE_REDIR_MAX_INTERFACES; i++) { - if (!nss_gre_redir_stats_get(i, &get_stats)) { + if (!nss_gre_redir_get_stats(i, &get_stats)) { continue; } @@ -340,15 +340,15 @@ static struct rtnl_link_stats64 *nss_nlg if (found == false) return NULL; - stats->tx_bytes = get_stats.tstats.tx_bytes; - stats->tx_packets = get_stats.tstats.tx_packets; - stats->rx_bytes = get_stats.tstats.rx_bytes; - stats->rx_packets = get_stats.tstats.rx_packets; - for (i = 0;i < ARRAY_SIZE(get_stats.tstats.rx_dropped); i++) { - stats->rx_dropped += get_stats.tstats.rx_dropped[i]; + stats->tx_bytes = get_stats.node_stats.tx_bytes; + stats->tx_packets = get_stats.node_stats.tx_packets; + stats->rx_bytes = get_stats.node_stats.rx_bytes; + stats->rx_packets = get_stats.node_stats.rx_packets; + for (i = 0;i < ARRAY_SIZE(get_stats.node_stats.rx_dropped); i++) { + stats->rx_dropped += get_stats.node_stats.rx_dropped[i]; } - stats->tx_dropped = get_stats.tstats.tx_dropped; + stats->tx_dropped = get_stats.tx_dropped; return stats; } --- a/netlink/nss_nlipsec.c +++ b/netlink/nss_nlipsec.c @@ -1,12 +1,9 @@ /* ************************************************************************** - * Copyright (c) 2015-2016,2018-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. - * + * Copyright (c) 2015-2016,2018-2020 The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. - * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -52,8 +49,8 @@ static int nss_nlipsec_op_create_tunnel( static int nss_nlipsec_op_destroy_tunnel(struct sk_buff *skb, struct genl_info *info); static int nss_nlipsec_op_add_sa(struct sk_buff *skb, struct genl_info *info); static int nss_nlipsec_op_delete_sa(struct sk_buff *skb, struct genl_info *info); -static int nss_nlipsec_op_add_flow(struct sk_buff *skb, struct genl_info *info); -static int nss_nlipsec_op_delete_flow(struct sk_buff *skb, struct genl_info *info); +// static int nss_nlipsec_op_add_flow(struct sk_buff *skb, struct genl_info *info); +// static int nss_nlipsec_op_delete_flow(struct sk_buff *skb, struct genl_info *info); /* * Hold netdevice references @@ -111,14 +108,14 @@ static struct genl_ops nss_nlipsec_ops[] .cmd = NSS_NLIPSEC_CMD_DEL_SA, .doit = nss_nlipsec_op_delete_sa, }, - { /* Add flow */ - .cmd = NSS_NLIPSEC_CMD_ADD_FLOW, - .doit = nss_nlipsec_op_add_flow, - }, - { /* Delete flow */ - .cmd = NSS_NLIPSEC_CMD_DEL_FLOW, - .doit = nss_nlipsec_op_delete_flow, - }, + // { /* Add flow */ + // .cmd = NSS_NLIPSEC_CMD_ADD_FLOW, + // .doit = nss_nlipsec_op_add_flow, + // }, + // { /* Delete flow */ + // .cmd = NSS_NLIPSEC_CMD_DEL_FLOW, + // .doit = nss_nlipsec_op_delete_flow, + // }, }; /* @@ -329,7 +326,7 @@ int nss_nlipsec_get_mtu(struct net_devic static int nss_nlipsec_op_create_tunnel(struct sk_buff *skb, struct genl_info *info) { struct nss_nlipsec_rule *nl_rule; - struct nss_ipsecmgr_callback cb = {0}; + struct nss_ipsecmgr_callback cb; struct nss_nlcmn *nl_cm; struct net_device *dev; struct sk_buff *resp; @@ -511,8 +508,6 @@ static struct nss_nlipsec_rule *nss_nlip dev_put(*dev); return NULL; } - - dev_put(*dev); return nl_rule; } @@ -552,7 +547,7 @@ static int nss_nlipsec_op_add_sa(struct sa_data->cmn.keys.auth_key = sa_rule->auth_key; sa_data->cmn.keys.nonce = sa_rule->nonce; - error = nss_ipsecmgr_sa_add_sync(dev, &sa_rule->tuple, sa_data, &if_num); + error = nss_ipsecmgr_sa_add(dev, &sa_rule->tuple, sa_data, &if_num); if (error) { nss_nl_error("%d: Failed to add SA for net device(%s), error:%d\n", pid, nl_rule->ifname, error); goto free_dev; @@ -630,72 +625,73 @@ static int nss_nlipsec_op_delete_sa(stru * nss_nlipsec_op_add_flow() * Add a flow */ -static int nss_nlipsec_op_add_flow(struct sk_buff *skb, struct genl_info *info) -{ - struct nss_ipsecmgr_flow_tuple *flow_tuple; - struct nss_ipsecmgr_sa_tuple *sa_tuple; - struct nss_nlipsec_rule *nl_rule; - struct net_device *dev; - uint32_t pid; - int error = 0; - - nl_rule = nss_nlipsec_get_rule(info, NSS_NLIPSEC_CMD_ADD_FLOW, &dev); - if (!nl_rule) { - nss_nl_error("Failed to extract SA data\n"); - return -EINVAL; - } - - pid = nl_rule->cm.pid; - nss_nl_error("%d: device(%s)", pid, dev->name); - - flow_tuple = &nl_rule->rule.flow.tuple; - sa_tuple = &nl_rule->rule.flow.sa; - - error = nss_ipsecmgr_flow_add_sync(dev, flow_tuple, sa_tuple); - if (error) { - nss_nl_error("%d: Failed to add subnet for net_device(%s)", pid, nl_rule->ifname); - } - - /* - * dev_put for dev_get done on nss_nlipsec_get_rule - */ - dev_put(dev); - return error; -} +// static int nss_nlipsec_op_add_flow(struct sk_buff *skb, struct genl_info *info) +// { +// struct nss_ipsecmgr_flow_tuple *flow_tuple; +// struct nss_ipsecmgr_sa_tuple *sa_tuple; +// struct nss_nlipsec_rule *nl_rule; +// struct net_device *dev; +// uint32_t pid; +// int error = 0; +// +// nl_rule = nss_nlipsec_get_rule(info, NSS_NLIPSEC_CMD_ADD_FLOW, &dev); +// if (!nl_rule) { +// nss_nl_error("Failed to extract SA data\n"); +// return -EINVAL; +// } +// +// pid = nl_rule->cm.pid; +// nss_nl_error("%d: device(%s)", pid, dev->name); +// +// flow_tuple = &nl_rule->rule.flow.tuple; +// sa_tuple = &nl_rule->rule.flow.sa; +// +// //struct nss_ipsecmgr_ref *nss_ipsecmgr_flow_alloc(struct nss_ipsecmgr_priv *priv, struct nss_ipsecmgr_key *key) +// error = nss_ipsecmgr_flow_add_sync(dev, flow_tuple, sa_tuple); +// if (error) { +// nss_nl_error("%d: Failed to add subnet for net_device(%s)", pid, nl_rule->ifname); +// } +// +// /* +// * dev_put for dev_get done on nss_nlipsec_get_rule +// */ +// dev_put(dev); +// return error; +// } /* * nss_nlipsec_op_delete_flow() * Delete a flow */ -static int nss_nlipsec_op_delete_flow(struct sk_buff *skb, struct genl_info *info) -{ - struct nss_ipsecmgr_flow_tuple *flow_tuple; - struct nss_ipsecmgr_sa_tuple *sa_tuple; - struct nss_nlipsec_rule *nl_rule; - struct net_device *dev; - uint32_t pid; - int error = 0; - - nl_rule = nss_nlipsec_get_rule(info, NSS_NLIPSEC_CMD_DEL_FLOW, &dev); - if (!nl_rule) { - nss_nl_error("Failed to extract SA data\n"); - return -EINVAL; - } - - pid = nl_rule->cm.pid; - nss_nl_error("%d: device(%s)", pid, dev->name); - - flow_tuple = &nl_rule->rule.flow.tuple; - sa_tuple = &nl_rule->rule.flow.sa; - - nss_ipsecmgr_flow_del(dev, flow_tuple, sa_tuple); - - /* - * dev_put for dev_get done on nss_nlipsec_get_rule - */ - dev_put(dev); - return error; -} +// static int nss_nlipsec_op_delete_flow(struct sk_buff *skb, struct genl_info *info) +// { +// struct nss_ipsecmgr_flow_tuple *flow_tuple; +// struct nss_ipsecmgr_sa_tuple *sa_tuple; +// struct nss_nlipsec_rule *nl_rule; +// struct net_device *dev; +// uint32_t pid; +// int error = 0; +// +// nl_rule = nss_nlipsec_get_rule(info, NSS_NLIPSEC_CMD_DEL_FLOW, &dev); +// if (!nl_rule) { +// nss_nl_error("Failed to extract SA data\n"); +// return -EINVAL; +// } +// +// pid = nl_rule->cm.pid; +// nss_nl_error("%d: device(%s)", pid, dev->name); +// +// flow_tuple = &nl_rule->rule.flow.tuple; +// sa_tuple = &nl_rule->rule.flow.sa; +// +// nss_ipsecmgr_flow_del(dev, flow_tuple, sa_tuple); +// +// /* +// * dev_put for dev_get done on nss_nlipsec_get_rule +// */ +// dev_put(dev); +// return error; +// } /* * nss_nlipsec_init() --- a/netlink/nss_nlipv4.c +++ b/netlink/nss_nlipv4.c @@ -336,20 +336,6 @@ static int nss_nlipv4_verify_conn_rule(s tuple->return_ident, tuple->flow_ident); break; - case NSS_NL_IFTYPE_TUNNEL_GRE: - /* - * Currently this implementation is only for gre_redir - */ - conn->flow_interface_num = nss_nlgre_redir_cmd_get_ifnum(flow_dev, tuple->protocol); - if (conn->flow_interface_num < 0 ) { - nss_nl_error("%px: Failed to get flow interface number (dev:%s, type:%d)\n", - flow_dev, flow_dev->name, flow_iftype); - return -EINVAL; - } - - conn->flow_mtu = nss_nlgre_redir_cmd_get_mtu(flow_dev, NSS_GRE_REDIR_IP_HDR_TYPE_IPV4, conn->flow_interface_num); - break; - case NSS_NL_IFTYPE_VLAN: conn->flow_interface_num = nss_cmn_get_interface_number_by_dev(vlan_dev_real_dev(flow_dev)); if (conn->flow_interface_num < 0 ) { @@ -396,17 +382,6 @@ static int nss_nlipv4_verify_conn_rule(s tuple->return_ident, tuple->flow_ident); break; - case NSS_NL_IFTYPE_TUNNEL_GRE: - conn->return_interface_num = nss_nlgre_redir_cmd_get_ifnum(return_dev, tuple->protocol); - if (conn->return_interface_num < 0 ) { - nss_nl_error("%px: Failed to get return interface number (dev:%s, type:%d)\n", - return_dev, return_dev->name, return_iftype); - return -EINVAL; - } - - conn->return_mtu = nss_nlgre_redir_cmd_get_mtu(return_dev, NSS_GRE_REDIR_IP_HDR_TYPE_IPV4, conn->return_interface_num); - break; - case NSS_NL_IFTYPE_VLAN: conn->return_interface_num = nss_cmn_get_interface_number_by_dev(vlan_dev_real_dev(return_dev)); if (conn->return_interface_num < 0 ) { @@ -623,27 +598,6 @@ static int nss_nlipv4_verify_vlan_rule(s } /* - * nss_nlipv4_verify_identifier() - * verify and override identifier rule entries - */ -static int nss_nlipv4_verify_identifier(struct nss_ipv4_rule_create_msg *msg) -{ - struct nss_ipv4_identifier_rule *identifier = &msg->identifier; - const size_t rule_sz = sizeof(struct nss_ipv4_identifier_rule); - uint16_t valid; - - /* - * if identifier is not valid, set identifier rule to 0 - */ - valid = msg->valid_flags & NSS_IPV4_RULE_CREATE_IDENTIFIER_VALID; - if (!valid) { - memset(identifier, 0, rule_sz); - } - - return 0; -} - -/* * nss_nlipv4_process_notify() * process notification messages from NSS */ @@ -823,15 +777,6 @@ static int nss_nlipv4_ops_create_rule(st } /* - * check identifier - */ - error = nss_nlipv4_verify_identifier(&nim->msg.rule_create); - if (error < 0) { - nss_nl_error("%d:invalid identifier rule information passed\n", pid); - goto done; - } - - /* * copy the NL message for response */ resp = nss_nl_copy_msg(skb); @@ -855,10 +800,6 @@ static int nss_nlipv4_ops_create_rule(st * Push Rule to NSS */ tx_status = nss_ipv4_tx_sync(gbl_ctx.nss, nim); - - /* TODO: Handle the case where firmware has received the response - * and there is a failure in firmware. - */ if (tx_status != NSS_TX_SUCCESS) { nss_nl_error("%d:unable to send IPv4 rule create, status(%d)\n", pid, tx_status); error = -EBUSY; @@ -933,10 +874,6 @@ static int nss_nlipv4_ops_destroy_rule(s * Push rule to NSS */ tx_status = nss_ipv4_tx_sync(gbl_ctx.nss, nim); - - /* TODO: Handle the case where firmware has received the response - * and there is a failure in firmware. - */ if (tx_status != NSS_TX_SUCCESS) { nss_nl_error("%d:unable to send IPv4 rule delete, status(%d)\n", pid, tx_status); return -EBUSY; --- a/netlink/nss_nlipv6.c +++ b/netlink/nss_nlipv6.c @@ -353,17 +353,6 @@ static int nss_nlipv6_verify_conn_rule(s tuple->return_ident, tuple->flow_ident); break; - case NSS_NL_IFTYPE_TUNNEL_GRE: - conn->flow_interface_num = nss_nlgre_redir_cmd_get_ifnum(flow_dev, tuple->protocol); - if (conn->flow_interface_num < 0 ) { - nss_nl_error("%px: Failed to get flow interface number (dev:%s, type:%d)\n", - flow_dev, flow_dev->name, flow_iftype); - return -EINVAL; - } - - conn->flow_mtu = nss_nlgre_redir_cmd_get_mtu(flow_dev, NSS_GRE_REDIR_IP_HDR_TYPE_IPV6, conn->flow_interface_num); - break; - case NSS_NL_IFTYPE_VLAN: conn->flow_interface_num = nss_cmn_get_interface_number_by_dev(vlan_dev_real_dev(flow_dev)); if (conn->flow_interface_num < 0 ) { @@ -411,17 +400,6 @@ static int nss_nlipv6_verify_conn_rule(s tuple->return_ident, tuple->flow_ident); break; - case NSS_NL_IFTYPE_TUNNEL_GRE: - conn->return_interface_num = nss_nlgre_redir_cmd_get_ifnum(return_dev, tuple->protocol); - if (conn->return_interface_num < 0 ) { - nss_nl_error("%px: Failed to get return interface number (dev:%s, type:%d)\n", - return_dev, return_dev->name, return_iftype); - return -EINVAL; - } - - conn->return_mtu = nss_nlgre_redir_cmd_get_mtu(return_dev, NSS_GRE_REDIR_IP_HDR_TYPE_IPV6, conn->return_interface_num); - break; - case NSS_NL_IFTYPE_VLAN: conn->return_interface_num = nss_cmn_get_interface_number_by_dev(vlan_dev_real_dev(return_dev)); if (conn->return_interface_num < 0 ) { @@ -624,27 +602,6 @@ static int nss_nlipv6_verify_vlan_rule(s } /* - * nss_nlipv6_verify_identifier() - * verify and override identifier rule entries - */ -static int nss_nlipv6_verify_identifier(struct nss_ipv6_rule_create_msg *msg) -{ - struct nss_ipv6_identifier_rule *identifier = &msg->identifier; - const size_t rule_sz = sizeof(struct nss_ipv6_identifier_rule); - uint16_t valid; - - /* - * if identifier is not valid, set identifier rule to 0 - */ - valid = msg->valid_flags & NSS_IPV6_RULE_CREATE_IDENTIFIER_VALID; - if (!valid) { - memset(identifier, 0, rule_sz); - } - - return 0; -} - -/* * nss_nlipv6_process_notify() * process notification messages from NSS */ @@ -817,15 +774,6 @@ static int nss_nlipv6_ops_create_rule(st } /* - * check identifier - */ - error = nss_nlipv6_verify_identifier(&nim->msg.rule_create); - if (error < 0) { - nss_nl_error("%d:invalid identifier rule information passed\n", pid); - goto done; - } - - /* * copy the NL message for response */ resp = nss_nl_copy_msg(skb); @@ -855,10 +803,6 @@ static int nss_nlipv6_ops_create_rule(st * Push Rule to NSS */ tx_status = nss_ipv6_tx_sync(gbl_ctx.nss, nim); - - /* TODO: Handle the case where firmware has received the response - * and there is a failure in firmware. - */ if (tx_status != NSS_TX_SUCCESS) { nss_nl_error("%d:unable to send IPV6 rule create, status(%d)\n", pid, tx_status); error = -EBUSY; @@ -938,10 +882,6 @@ static int nss_nlipv6_ops_destroy_rule(s * Push rule to NSS */ tx_status = nss_ipv6_tx_sync(gbl_ctx.nss, nim); - - /* TODO: Handle the case where firmware has received the response - * and there is a failure in firmware. - */ if (tx_status != NSS_TX_SUCCESS) { nss_nl_error("%d:unable to send IPV6 rule delete, status(%d)\n", pid, tx_status); return -EBUSY; --- /dev/null +++ b/nss_connmgr_tunipip6.c @@ -0,0 +1,503 @@ +/* + ************************************************************************** + * Copyright (c) 2014, 2017-2018, The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + ************************************************************************** + */ + +/* + * nss_tunipip6.c + * + * This file is the NSS DS-lit and IPP6 tunnel module + * ------------------------REVISION HISTORY----------------------------- + * Qualcomm Atheros 15/sep/2013 Created + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,9,0)) +#include +#else +#include +#endif +#include +#include +#include + +/* + * NSS tunipip6 debug macros + */ +#if (NSS_TUNIPIP6_DEBUG_LEVEL < 1) +#define nss_tunipip6_assert(fmt, args...) +#else +#define nss_tunipip6_assert(c) if (!(c)) { BUG_ON(!(c)); } +#endif + +#if defined(CONFIG_DYNAMIC_DEBUG) + +/* + * Compile messages for dynamic enable/disable + */ +#define nss_tunipip6_warning(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) +#define nss_tunipip6_info(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) +#define nss_tunipip6_trace(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) +#else + +/* + * Statically compile messages at different levels + */ +#if (NSS_TUNIPIP6_DEBUG_LEVEL < 2) +#define nss_tunipip6_warning(s, ...) +#else +#define nss_tunipip6_warning(s, ...) pr_warn("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) +#endif + +#if (NSS_TUNIPIP6_DEBUG_LEVEL < 3) +#define nss_tunipip6_info(s, ...) +#else +#define nss_tunipip6_info(s, ...) pr_notice("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) +#endif + +#if (NSS_TUNIPIP6_DEBUG_LEVEL < 4) +#define nss_tunipip6_trace(s, ...) +#else +#define nss_tunipip6_trace(s, ...) pr_info("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__) +#endif +#endif + +/* + * tunipip6 stats structure + */ +struct nss_tunipip6_stats { + uint32_t rx_packets; /* Number of received packets */ + uint32_t rx_bytes; /* Number of received bytes */ + uint32_t tx_packets; /* Number of transmitted packets */ + uint32_t tx_bytes; /* Number of transmitted bytes */ +}; + +/* + * nss_tunipip6_encap_exception() + * Exception handler registered to NSS driver. + * + * This function is called when no rule is found for successful encapsulation. + */ +static void nss_tunipip6_encap_exception(struct net_device *dev, struct sk_buff *skb, __attribute__((unused)) struct napi_struct *napi) +{ + skb->dev = dev; + nss_tunipip6_info("received - %d bytes name %s ver %x\n", + skb->len, dev->name, (skb->data[0] >> 4)); + + skb->protocol = htons(ETH_P_IP); + skb_reset_network_header(skb); + skb->pkt_type = PACKET_HOST; + skb->skb_iif = dev->ifindex; + skb->ip_summed = CHECKSUM_NONE; + netif_receive_skb(skb); +} + +/* + * nss_tunipip6_decap_exception() + * Exception handler registered to NSS driver. + * + * This function is called when no rule is found for successful decapsulation. + */ +static void nss_tunipip6_decap_exception(struct net_device *dev, struct sk_buff *skb, __attribute__((unused)) struct napi_struct *napi) +{ + skb->dev = dev; + nss_tunipip6_info("received - %d bytes name %s ver %x\n", + skb->len, dev->name, (skb->data[0] >> 4)); + + skb->protocol = htons(ETH_P_IPV6); + skb_reset_network_header(skb); + skb->pkt_type = PACKET_HOST; + skb->skb_iif = dev->ifindex; + skb->ip_summed = CHECKSUM_NONE; + netif_receive_skb(skb); +} + +/* + * nss_tunipip6_update_dev_stats + * Update the Dev stats received from NetAp + */ +static void nss_tunipip6_update_dev_stats(struct net_device *dev, + struct nss_tunipip6_stats_sync_msg *sync_stats) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) + struct pcpu_sw_netstats stats; + + u64_stats_init(&stats.syncp); + u64_stats_update_begin(&stats.syncp); + stats.rx_packets = sync_stats->node_stats.rx_packets; + stats.rx_bytes = sync_stats->node_stats.rx_bytes; + stats.tx_packets = sync_stats->node_stats.tx_packets; + stats.tx_bytes = sync_stats->node_stats.tx_bytes; + u64_stats_update_end(&stats.syncp); +#else + struct nss_tunipip6_stats stats; + + stats.rx_packets = sync_stats->node_stats.rx_packets; + stats.rx_bytes = sync_stats->node_stats.rx_bytes; + stats.tx_packets = sync_stats->node_stats.tx_packets; + stats.tx_bytes = sync_stats->node_stats.tx_bytes; +#endif + + dev->stats.rx_dropped += nss_cmn_rx_dropped_sum(&sync_stats->node_stats); + ip6_update_offload_stats(dev, (void *)&stats); + +} + +/* + * nss_tunipip6_event_receive() + * Event Callback to receive events from NSS. + */ +void nss_tunipip6_event_receive(void *if_ctx, struct nss_tunipip6_msg *tnlmsg) +{ + struct net_device *netdev = NULL; + netdev = (struct net_device *)if_ctx; + + switch (tnlmsg->cm.type) { + case NSS_TUNIPIP6_RX_STATS_SYNC: + nss_tunipip6_update_dev_stats(netdev, (struct nss_tunipip6_stats_sync_msg *)&tnlmsg->msg.stats_sync); + break; + + default: + nss_tunipip6_info("%s: Unknown Event from NSS", __func__); + break; + } +} + +/* + * nss_tunipip6_dev_up() + * IPIP6 Tunnel device i/f up handler + */ +int nss_tunipip6_dev_up(struct net_device *netdev) +{ + struct ip6_tnl *tunnel; + struct nss_tunipip6_msg tnlmsg; + struct nss_tunipip6_create_msg *tnlcfg; + struct flowi6 *fl6; + uint32_t fmr_number = 0; + int inner_ifnum, outer_ifnum; + uint32_t features = 0; + nss_tx_status_t status; + struct nss_ctx_instance *nss_ctx; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + struct __ip6_tnl_fmr *fmr; +#endif + + /* + * Validate netdev for ipv6-in-ipv4 Tunnel + */ + if (netdev->type != ARPHRD_TUNNEL6 ) { + return NOTIFY_DONE; + } + + tunnel = (struct ip6_tnl *)netdev_priv(netdev); + + /* + * Find the Tunnel device flow information + */ + fl6 = &tunnel->fl.u.ip6; + + nss_tunipip6_trace("%p: Tunnel Param srcaddr %x:%x:%x:%x daddr %x:%x:%x:%x\n", netdev, + fl6->saddr.s6_addr32[0], fl6->saddr.s6_addr32[1], + fl6->saddr.s6_addr32[2], fl6->saddr.s6_addr32[3], + fl6->daddr.s6_addr32[0], fl6->daddr.s6_addr32[1], + fl6->daddr.s6_addr32[2], fl6->daddr.s6_addr32[3] ); + nss_tunipip6_trace("%p: Hop limit %d\n", netdev, tunnel->parms.hop_limit); + nss_tunipip6_trace("%p: Tunnel param flag %x fl6.flowlabel %x\n", netdev, tunnel->parms.flags, fl6->flowlabel); + + inner_ifnum = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_INNER); + if (inner_ifnum < 0) { + nss_tunipip6_warning("%p: Request interface number failed\n", netdev); + goto inner_alloc_fail; + } + + outer_ifnum = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_OUTER); + if (outer_ifnum < 0) { + nss_tunipip6_warning("%p: Request interface number failed\n", netdev); + goto outer_alloc_fail; + } + + /* + * Register ipip6 tunnel with NSS + */ + nss_ctx = nss_register_tunipip6_if(inner_ifnum, + NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_INNER, + nss_tunipip6_encap_exception, + nss_tunipip6_event_receive, + netdev, + features); + if (!nss_ctx) { + nss_tunipip6_warning("%p: nss_register_tunipip6_if Failed\n", netdev); + goto inner_reg_fail; + } + + nss_ctx = nss_register_tunipip6_if(outer_ifnum, + NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_OUTER, + nss_tunipip6_decap_exception, + nss_tunipip6_event_receive, + netdev, + features); + if (!nss_ctx) { + nss_tunipip6_warning("%p: nss_register_tunipip6_if Failed\n", netdev); + goto outer_reg_fail; + } + + nss_tunipip6_trace("%p: nss_register_tunipip6_if Success\n", netdev); + + /* + * Prepare The Tunnel configuration parameter to send to nss + */ + memset(&tnlmsg, 0, sizeof(struct nss_tunipip6_msg)); + tnlcfg = &tnlmsg.msg.tunipip6_create; + + tnlcfg->saddr[0] = ntohl(fl6->saddr.s6_addr32[0]); + tnlcfg->saddr[1] = ntohl(fl6->saddr.s6_addr32[1]); + tnlcfg->saddr[2] = ntohl(fl6->saddr.s6_addr32[2]); + tnlcfg->saddr[3] = ntohl(fl6->saddr.s6_addr32[3]); + tnlcfg->daddr[0] = ntohl(fl6->daddr.s6_addr32[0]); + tnlcfg->daddr[1] = ntohl(fl6->daddr.s6_addr32[1]); + tnlcfg->daddr[2] = ntohl(fl6->daddr.s6_addr32[2]); + tnlcfg->daddr[3] = ntohl(fl6->daddr.s6_addr32[3]); + tnlcfg->hop_limit = tunnel->parms.hop_limit; + tnlcfg->flags = ntohl(tunnel->parms.flags); + + /* + * Flow Label In kernel is stored in big endian format. + */ + tnlcfg->flowlabel = fl6->flowlabel; + tnlcfg->draft03 = tunnel->parms.draft03; + + /* + * Configure FMR table up to MAX_FMR_NUMBER, the rest will be forwarded to BR + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) + for (fmr = tunnel->parms.fmrs; fmr && fmr_number < NSS_TUNIPIP6_MAX_FMR_NUMBER; fmr = fmr->next, fmr_number++) { + tnlcfg->fmr[fmr_number].ip6_prefix[0] = ntohl(fmr->ip6_prefix.s6_addr32[0]); + tnlcfg->fmr[fmr_number].ip6_prefix[1] = ntohl(fmr->ip6_prefix.s6_addr32[1]); + tnlcfg->fmr[fmr_number].ip6_prefix[2] = ntohl(fmr->ip6_prefix.s6_addr32[2]); + tnlcfg->fmr[fmr_number].ip6_prefix[3] = ntohl(fmr->ip6_prefix.s6_addr32[3]); + tnlcfg->fmr[fmr_number].ip4_prefix = ntohl(fmr->ip4_prefix.s_addr); + tnlcfg->fmr[fmr_number].ip6_prefix_len = fmr->ip6_prefix_len; + tnlcfg->fmr[fmr_number].ip4_prefix_len = fmr->ip4_prefix_len; + tnlcfg->fmr[fmr_number].ea_len = fmr->ea_len; + tnlcfg->fmr[fmr_number].offset = fmr->offset; + } +#endif + tnlcfg->fmr_number = fmr_number; + + /* + * Updating sibling_if_num for encap interface. + */ + tnlcfg->sibling_if_num = outer_ifnum; + + nss_tunipip6_trace("%p: Tunnel Param srcaddr %x:%x:%x:%x daddr %x:%x:%x:%x\n", netdev, + tnlcfg->saddr[0], tnlcfg->saddr[1], + tnlcfg->saddr[2], tnlcfg->saddr[3], + tnlcfg->daddr[0], tnlcfg->daddr[1], + tnlcfg->daddr[2], tnlcfg->daddr[3] ); + + /* + * Send configure message to encap interface. + */ + nss_tunipip6_msg_init(&tnlmsg, inner_ifnum, NSS_TUNIPIP6_TX_ENCAP_IF_CREATE, + sizeof(struct nss_tunipip6_create_msg), NULL, NULL); + + nss_tunipip6_trace("%p: Sending IPIP6 tunnel i/f up command to NSS %p\n", netdev, nss_ctx); + status = nss_tunipip6_tx(nss_ctx, &tnlmsg); + if (status != NSS_TX_SUCCESS) { + nss_tunipip6_warning("%p: Tunnel up command error %d\n", netdev, status); + goto config_fail; + } + + /* + * Updating sibling_if_num for decap interface. + */ + tnlcfg->sibling_if_num = inner_ifnum; + + /* + * Send configure message to decap interface. + */ + nss_tunipip6_msg_init(&tnlmsg, outer_ifnum, NSS_TUNIPIP6_TX_DECAP_IF_CREATE, + sizeof(struct nss_tunipip6_create_msg), NULL, NULL); + + nss_tunipip6_trace("%p: Sending IPIP6 tunnel i/f up command to NSS %p\n", netdev, nss_ctx); + status = nss_tunipip6_tx(nss_ctx, &tnlmsg); + if (status != NSS_TX_SUCCESS) { + nss_tunipip6_warning("%p: Tunnel up command error %d\n", netdev, status); + goto config_fail; + } + return NOTIFY_DONE; + +config_fail: + nss_unregister_tunipip6_if(outer_ifnum); +outer_reg_fail: + nss_unregister_tunipip6_if(inner_ifnum); +inner_reg_fail: + status = nss_dynamic_interface_dealloc_node(outer_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_OUTER); + if (status != NSS_TX_SUCCESS) { + nss_tunipip6_warning("%p: Unable to dealloc the node[%d] in the NSS fw!\n", netdev, outer_ifnum); + } +outer_alloc_fail: + status = nss_dynamic_interface_dealloc_node(inner_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_INNER); + if (status != NSS_TX_SUCCESS) { + nss_tunipip6_warning("%p: Unable to dealloc the node[%d] in the NSS fw!\n", netdev, inner_ifnum); + } +inner_alloc_fail: + return NOTIFY_DONE; +} + +/* + * nss_tunipip6_dev_down() + * IPP6 Tunnel device i/f down handler + */ +int nss_tunipip6_dev_down(struct net_device *netdev) +{ + int inner_ifnum, outer_ifnum; + nss_tx_status_t status; + + /* + * Validate netdev for ipv6-in-ipv4 Tunnel + */ + if (netdev->type != ARPHRD_TUNNEL6) { + return NOTIFY_DONE; + } + + /* + * Check if tunnel ipip6 is registered ? + */ + inner_ifnum = nss_cmn_get_interface_number_by_dev_and_type(netdev, NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_INNER); + if (inner_ifnum < 0) { + nss_tunipip6_warning("%p: Net device is not registered with nss\n", netdev); + return NOTIFY_DONE; + } + + outer_ifnum = nss_cmn_get_interface_number_by_dev_and_type(netdev, NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_OUTER); + if (outer_ifnum < 0) { + nss_tunipip6_warning("%p: Net device is not registered with nss\n", netdev); + return NOTIFY_DONE; + } + + /* + * Un-Register IPIP6 tunnel with NSS + */ + nss_unregister_tunipip6_if(inner_ifnum); + nss_unregister_tunipip6_if(outer_ifnum); + + status = nss_dynamic_interface_dealloc_node(inner_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_INNER); + if (status != NSS_TX_SUCCESS) { + nss_tunipip6_warning("%p: Dealloc node failure\n", netdev); + return NOTIFY_DONE; + } + + status = nss_dynamic_interface_dealloc_node(outer_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_OUTER); + if (status != NSS_TX_SUCCESS) { + nss_tunipip6_warning("%p: Dealloc node failure\n", netdev); + return NOTIFY_DONE; + } + + return NOTIFY_DONE; +} + +/* + * nss_tunipip6_dev_event() + * Net device notifier for ipip6 module + */ +static int nss_tunipip6_dev_event(struct notifier_block *nb, + unsigned long event, void *dev) +{ +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 0)) + struct net_device *netdev = (struct net_device *)dev; +#else + struct net_device *netdev = netdev_notifier_info_to_dev(dev); +#endif + + switch (event) { + case NETDEV_UP: + nss_tunipip6_trace("%p: NETDEV_UP :event %lu name %s\n", netdev, event, netdev->name); + return nss_tunipip6_dev_up(netdev); + + case NETDEV_DOWN: + nss_tunipip6_trace("%p: NETDEV_DOWN :event %lu name %s\n", netdev, event, netdev->name); + return nss_tunipip6_dev_down(netdev); + + default: + nss_tunipip6_trace("%p: Unhandled notifier dev %s event %x\n", netdev, netdev->name, (int)event); + break; + } + + return NOTIFY_DONE; +} + +/* + * Linux Net device Notifier + */ +struct notifier_block nss_tunipip6_notifier = { + .notifier_call = nss_tunipip6_dev_event, +}; + +/* + * nss_tunipip6_init_module() + * Tunnel ipip6 module init function + */ +int __init nss_tunipip6_init_module(void) +{ +#ifdef CONFIG_OF + /* + * If the node is not compatible, don't do anything. + */ + if (!of_find_node_by_name(NULL, "nss-common")) { + return 0; + } +#endif + nss_tunipip6_info("module (platform - IPQ806x , %s) loaded\n", + NSS_CLIENT_BUILD_ID); + + register_netdevice_notifier(&nss_tunipip6_notifier); + nss_tunipip6_trace("Netdev Notifier registerd\n"); + + + return 0; +} + +/* + * nss_tunipip6_exit_module() + * Tunnel ipip6 module exit function + */ +void __exit nss_tunipip6_exit_module(void) +{ +#ifdef CONFIG_OF + + /* + * If the node is not compatible, don't do anything. + */ + if (!of_find_node_by_name(NULL, "nss-common")) { + return; + } +#endif + + unregister_netdevice_notifier(&nss_tunipip6_notifier); + nss_tunipip6_info("module unloaded\n"); +} + +module_init(nss_tunipip6_init_module); +module_exit(nss_tunipip6_exit_module); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("NSS tunipip6 offload manager"); --- a/nss_qdisc/Makefile +++ b/nss_qdisc/Makefile @@ -9,18 +9,16 @@ endif ccflags-y += -Wall -Werror obj-m += qca-nss-qdisc.o -qca-nss-qdisc-objs := nss_bf.o \ - nss_blackhole.o \ - nss_codel.o \ +qca-nss-qdisc-objs := nss_qdisc.o \ nss_fifo.o \ - nss_htb.o \ - nss_prio.o \ - nss_qdisc.o \ - nss_qdisc_htable.o \ - nss_qdisc_stats.o \ + nss_codel.o \ nss_tbl.o \ - nss_wred.o \ - nss_wrr.o + nss_prio.o \ + nss_bf.o \ + nss_wrr.o \ + nss_htb.o \ + nss_blackhole.o \ + nss_wred.o ifeq ($(SoC),$(filter $(SoC),ipq807x ipq807x_64 ipq60xx ipq60xx_64)) qca-nss-qdisc-objs += nss_ppe.o \ --- a/nss_qdisc/igs/Makefile +++ b/nss_qdisc/igs/Makefile @@ -1,7 +1,6 @@ # Makefile for IGS (Ingress Shaping) ccflags-y += $(NSS_CCFLAGS) -I$(obj)/../../exports -ccflags-y += -DNSS_IGS_DEBUG_LEVEL=2 ccflags-y += -Wall -Werror obj-m += act_nssmirred.o --- a/nss_qdisc/igs/nss_mirred.c +++ b/nss_qdisc/igs/nss_mirred.c @@ -82,20 +82,24 @@ static const struct nla_policy nss_mirre * nss_mirred_init() * Initialize the nss mirred action. */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) static int nss_mirred_init(struct net *net, struct nlattr *nla, - struct nlattr *est, struct tc_action *tc_act, int ovr, - int bind) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) + struct nlattr *est, struct tc_action *tc_act, int ovr, + int bind) +{ +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) + struct nlattr *est, struct tc_action **tc_act, int ovr, + int bind, bool rtnl_held, struct tcf_proto *tp, + u32 flags, struct netlink_ext_ack *extack) { #else -static int nss_mirred_init(struct net *net, struct nlattr *nla, - struct nlattr *est, struct tc_action **tc_act, int ovr, - int bind, bool rtnl_held, struct tcf_proto *tp, - struct netlink_ext_ack *extack) + struct nlattr *est, struct tc_action **tc_act, + struct tcf_proto *tp, u32 flags, struct netlink_ext_ack *extack) { + bool bind = flags & TCA_ACT_FLAGS_BIND; +#endif struct tc_action_net *tn = net_generic(net, nss_mirred_net_id); u32 index; -#endif struct nlattr *arr[TC_NSS_MIRRED_MAX + 1]; struct tc_nss_mirred *parm; struct nss_mirred_tcf *act; @@ -239,8 +243,13 @@ static int nss_mirred_init(struct net *n } if (!ret) { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)) ret = tcf_idr_create(tn, index, est, tc_act, &nss_mirred_act_ops, bind, true); +#else + ret = tcf_idr_create(tn, index, est, tc_act, &nss_mirred_act_ops, + bind, true, 0); +#endif if (ret) { tcf_idr_cleanup(tn, index); return ret; --- a/nss_qdisc/nss_bf.c +++ b/nss_qdisc/nss_bf.c @@ -1,13 +1,9 @@ /* ************************************************************************** - * Copyright (c) 2014-2017, 2019-2021, The Linux Foundation. All rights reserved. - * - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. - * + * Copyright (c) 2014-2017, 2019-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. - * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -178,6 +174,11 @@ static int nss_bf_change_class(struct Qd */ qdisc_class_hash_grow(sch, &q->clhash); + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(&cl->nq); + nss_qdisc_info("Class %u successfully allocated\n", classid); } @@ -276,6 +277,11 @@ static void nss_bf_destroy_class(struct nss_qdisc_put(cl->qdisc); /* + * Stop the stats polling timer and free class + */ + nss_qdisc_stop_basic_stats_polling(&cl->nq); + + /* * Destroy the shaper in NSS */ nss_qdisc_destroy(&cl->nq); @@ -290,7 +296,11 @@ static void nss_bf_destroy_class(struct * nss_bf_delete_class() * Detaches a class from operation, but does not destroy it. */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) +static int nss_bf_delete_class(struct Qdisc *sch, unsigned long arg, struct netlink_ext_ack *extack) +#else static int nss_bf_delete_class(struct Qdisc *sch, unsigned long arg) +#endif { struct nss_bf_sched_data *q = qdisc_priv(sch); struct nss_bf_class_data *cl = (struct nss_bf_class_data *)arg; @@ -299,14 +309,11 @@ static int nss_bf_delete_class(struct Qd struct nss_qdisc *nq_child = (struct nss_qdisc *)qdisc_priv(cl->qdisc); /* - * If the class is the root class or has qdiscs attached, we do not - * support deleting it. + * Since all classes are leaf nodes in our case, we dont have to make + * that check. */ - if ((cl == &q->root) || (cl->qdisc != &noop_qdisc)) { - nss_qdisc_warning("Cannot delete bf class %x as it is the root " - "class or has child qdisc attached\n", cl->nq.qos_tag); + if (cl == &q->root) return -EBUSY; - } /* * The message to NSS should be sent to the parent of this class @@ -320,22 +327,14 @@ static int nss_bf_delete_class(struct Qd } sch_tree_lock(sch); + qdisc_reset(cl->qdisc); qdisc_class_hash_remove(&q->clhash, &cl->cl_common); refcnt = nss_qdisc_atomic_sub_return(&cl->nq); sch_tree_unlock(sch); - - /* - * For 5.4 and above kernels, calling nss_htb_destroy_class - * explicitly as there is no put_class which would have called - * nss_bf_destroy_class when refcnt becomes zero. - */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) - nss_bf_destroy_class(sch, cl); -#else if (!refcnt) { nss_qdisc_error("Reference count should not be zero for class %px\n", cl); } -#endif + return 0; } @@ -635,11 +634,6 @@ static int nss_bf_change_qdisc(struct Qd */ static void nss_bf_reset_class(struct nss_bf_class_data *cl) { - if (cl->qdisc == &noop_qdisc) { - nss_qdisc_trace("Class %x has no child qdisc to reset\n", cl->nq.qos_tag); - return; - } - nss_qdisc_reset(cl->qdisc); nss_qdisc_info("Nssbf class resetted %px\n", cl->qdisc); } @@ -721,6 +715,11 @@ static void nss_bf_destroy_qdisc(struct qdisc_class_hash_destroy(&q->clhash); /* + * Stop the polling of basic stats + */ + nss_qdisc_stop_basic_stats_polling(&q->nq); + + /* * Now we can go ahead and destroy the qdisc. * Note: We dont have to detach ourself from our parent because this * will be taken care of by the graft call. @@ -799,6 +798,11 @@ static int nss_bf_init_qdisc(struct Qdis return -EINVAL; } + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(&q->nq); + return 0; } --- a/nss_qdisc/nss_blackhole.c +++ b/nss_qdisc/nss_blackhole.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2014, 2016-2017, 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016-2017, 2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -90,6 +90,11 @@ static void nss_blackhole_destroy(struct { struct nss_qdisc *nq = (struct nss_qdisc *)qdisc_priv(sch); + /* + * Stop the polling of basic stats + */ + nss_qdisc_stop_basic_stats_polling(nq); + nss_qdisc_info("destroying qdisc %x\n", sch->handle); nss_qdisc_destroy(nq); } @@ -219,6 +224,11 @@ static int nss_blackhole_init(struct Qdi return -EINVAL; } + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(nq); + return 0; } --- a/nss_qdisc/nss_codel.c +++ b/nss_qdisc/nss_codel.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2014, 2016-2018, 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016-2018, 2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -155,6 +155,10 @@ static void nss_codel_destroy(struct Qdi { struct nss_codel_sched_data *q = qdisc_priv(sch); + /* + * Stop the polling of basic stats + */ + nss_qdisc_stop_basic_stats_polling(&q->nq); nss_qdisc_destroy(&q->nq); nss_codel_flow_queues_free(q); nss_qdisc_info("nss_codel destroyed"); @@ -451,6 +455,11 @@ static int nss_codel_init(struct Qdisc * return -EINVAL; } + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(nq); + return 0; } --- a/nss_qdisc/nss_fifo.c +++ b/nss_qdisc/nss_fifo.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2014, 2016-2017, 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016-2017, 2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -66,6 +66,11 @@ static void nss_fifo_destroy(struct Qdis { struct nss_qdisc *nq = (struct nss_qdisc *)qdisc_priv(sch); + /* + * Stop the polling of basic stats + */ + nss_qdisc_stop_basic_stats_polling(nq); + nss_qdisc_destroy(nq); nss_qdisc_info("nss_fifo destroyed"); } @@ -291,6 +296,11 @@ static int nss_fifo_init(struct Qdisc *s return -EINVAL; } + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(nq); + return 0; } --- a/nss_qdisc/nss_htb.c +++ b/nss_qdisc/nss_htb.c @@ -1,13 +1,9 @@ /* ************************************************************************** - * Copyright (c) 2014-2017, 2019-2021, The Linux Foundation. All rights reserved. - * - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. - * + * Copyright (c) 2014-2017, 2019-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. - * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -413,6 +409,11 @@ static int nss_htb_change_class(struct Q */ qdisc_class_hash_grow(sch, &q->clhash); + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(&cl->nq); + nss_qdisc_trace("class %x successfully allocated and initialized\n", classid); } @@ -502,6 +503,11 @@ static void nss_htb_destroy_class(struct nss_qdisc_put(cl->qdisc); /* + * Stop the stats polling timer and free class + */ + nss_qdisc_stop_basic_stats_polling(&cl->nq); + + /* * Destroy the shaper in NSS */ nss_qdisc_destroy(&cl->nq); @@ -516,7 +522,11 @@ static void nss_htb_destroy_class(struct * nss_htb_delete_class() * Detaches a class from operation, but does not destroy it. */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) +static int nss_htb_delete_class(struct Qdisc *sch, unsigned long arg, struct netlink_ext_ack *extack) +#else static int nss_htb_delete_class(struct Qdisc *sch, unsigned long arg) +#endif { struct nss_htb_sched_data *q = qdisc_priv(sch); struct nss_htb_class_data *cl = (struct nss_htb_class_data *)arg; @@ -524,12 +534,10 @@ static int nss_htb_delete_class(struct Q int refcnt; /* - * If the class still has child nodes or qdiscs, then we do not + * If the class still has child nodes, then we do not * support deleting it. */ - if ((cl->children) || (cl->qdisc != &noop_qdisc)) { - nss_qdisc_warning("Cannot delete htb class %x with child nodes " - "or qdisc attached\n", cl->nq.qos_tag); + if (cl->children) { return -EBUSY; } @@ -560,21 +568,16 @@ static int nss_htb_delete_class(struct Q } sch_tree_lock(sch); + qdisc_reset(cl->qdisc); qdisc_class_hash_remove(&q->clhash, &cl->sch_common); /* * If we are root class, we dont have to update our parent. * We simply deduct refcnt and return. - * For 5.4 and above kernels, calling nss_htb_destroy_class - * explicitly as there is no put_class which would have called - * nss_htb_destroy_class when refcnt becomes zero. */ if (!cl->parent) { refcnt = nss_qdisc_atomic_sub_return(&cl->nq); sch_tree_unlock(sch); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) - nss_htb_destroy_class(sch, cl); -#endif return 0; } @@ -593,14 +596,6 @@ static int nss_htb_delete_class(struct Q refcnt = nss_qdisc_atomic_sub_return(&cl->nq); sch_tree_unlock(sch); - /* - * For 5.4 and above kernels, calling nss_htb_destroy_class - * explicitly as there is no put_class which would have called - * nss_htb_destroy_class when refcnt becomes zero. - */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) - nss_htb_destroy_class(sch, cl); -#endif return 0; } @@ -903,11 +898,6 @@ static int nss_htb_change_qdisc(struct Q */ static void nss_htb_reset_class(struct nss_htb_class_data *cl) { - if (cl->qdisc == &noop_qdisc) { - nss_qdisc_trace("Class %x has no child qdisc to reset\n", cl->nq.qos_tag); - return; - } - nss_qdisc_reset(cl->qdisc); nss_qdisc_trace("htb class %x reset\n", cl->nq.qos_tag); } @@ -991,6 +981,11 @@ static void nss_htb_destroy_qdisc(struct qdisc_class_hash_destroy(&q->clhash); /* + * Stop the polling of basic stats + */ + nss_qdisc_stop_basic_stats_polling(&q->nq); + + /* * Now we can go ahead and destroy the qdisc. * Note: We dont have to detach ourself from our parent because this * will be taken care of by the graft call. @@ -1066,6 +1061,11 @@ static int nss_htb_init_qdisc(struct Qdi return -EINVAL; } + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(&q->nq); + return 0; } --- a/nss_qdisc/nss_ppe.c +++ b/nss_qdisc/nss_ppe.c @@ -1,8 +1,6 @@ /* ************************************************************************** * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. - * - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -128,7 +126,7 @@ static struct nss_ppe_res *nss_ppe_res_e spin_lock_bh(&ppe_port->lock); for (i = max; i > 0; i--) { - res = kzalloc(sizeof(struct nss_ppe_res), GFP_ATOMIC); + res = kzalloc(sizeof(struct nss_ppe_res), GFP_KERNEL); if (!res) { nss_qdisc_error("Free queue list allocation failed for port %u\n", port); goto fail; --- a/nss_qdisc/nss_prio.c +++ b/nss_qdisc/nss_prio.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2014-2017, 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, 2019-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -136,6 +136,11 @@ static void nss_prio_destroy(struct Qdis } /* + * Stop the polling of basic stats + */ + nss_qdisc_stop_basic_stats_polling(&q->nq); + + /* * Destroy the qdisc in NSS */ nss_qdisc_destroy(&q->nq); @@ -279,6 +284,10 @@ static int nss_prio_init(struct Qdisc *s return -EINVAL; } + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(&q->nq); return 0; } --- a/nss_qdisc/nss_qdisc.c +++ b/nss_qdisc/nss_qdisc.c @@ -29,6 +29,9 @@ void *nss_qdisc_ctx; /* Shaping context for nss_qdisc */ +#define NSS_QDISC_COMMAND_TIMEOUT (10*HZ) /* We set 10sec to be the command */ + /* timeout value for messages */ + /* * Defines related to root hash maintenance */ @@ -36,53 +39,6 @@ void *nss_qdisc_ctx; /* Shaping contex #define NSS_QDISC_ROOT_HASH_MASK (NSS_QDISC_ROOT_HASH_SIZE - 1) /* - * nss_qdisc_get_interface_msg() - * Returns the correct message that needs to be sent down to the NSS interface. - */ -int nss_qdisc_get_interface_msg(bool is_bridge, uint32_t msg_type) -{ - /* - * We re-assign the message based on whether this is for the I shaper - * or the B shaper. The is_bridge flag tells if we are on a bridge interface. - */ - if (is_bridge) { - switch (msg_type) { - case NSS_QDISC_IF_SHAPER_ASSIGN: - return NSS_IF_BSHAPER_ASSIGN; - case NSS_QDISC_IF_SHAPER_UNASSIGN: - return NSS_IF_BSHAPER_UNASSIGN; - case NSS_QDISC_IF_SHAPER_CONFIG: - return NSS_IF_BSHAPER_CONFIG; - default: - nss_qdisc_info("Unknown message type for a bridge - type %d", msg_type); - return -1; - } - } else { - switch (msg_type) { - case NSS_QDISC_IF_SHAPER_ASSIGN: - return NSS_IF_ISHAPER_ASSIGN; - case NSS_QDISC_IF_SHAPER_UNASSIGN: - return NSS_IF_ISHAPER_UNASSIGN; - case NSS_QDISC_IF_SHAPER_CONFIG: - return NSS_IF_ISHAPER_CONFIG; - default: - nss_qdisc_info("Unknown message type for an interface - type %d", msg_type); - return -1; - } - } -} - -/* - * nss_qdisc_msg_init() - * Initialize the qdisc specific message - */ -void nss_qdisc_msg_init(struct nss_if_msg *nim, uint16_t if_num, uint32_t msg_type, uint32_t len, - nss_if_msg_callback_t cb, void *app_data) -{ - nss_cmn_msg_init(&nim->cm, if_num, msg_type, len, (void *)cb, app_data); -} - -/* * nss_qdisc_interface_is_virtual() * Return true if it is redirect or bridge interface. */ @@ -165,6 +121,53 @@ static int nss_qdisc_ppe_init(struct Qdi #endif /* + * nss_qdisc_msg_init() + * Initialize the qdisc specific message + */ +static void nss_qdisc_msg_init(struct nss_if_msg *nim, uint16_t if_num, uint32_t msg_type, uint32_t len, + nss_if_msg_callback_t cb, void *app_data) +{ + nss_cmn_msg_init(&nim->cm, if_num, msg_type, len, (void*)cb, app_data); +} + +/* + * nss_qdisc_get_interface_msg() + * Returns the correct message that needs to be sent down to the NSS interface. + */ +static inline int nss_qdisc_get_interface_msg(bool is_bridge, uint32_t msg_type) +{ + /* + * We re-assign the message based on whether this is for the I shaper + * or the B shaper. The is_bridge flag tells if we are on a bridge interface. + */ + if (is_bridge) { + switch(msg_type) { + case NSS_QDISC_IF_SHAPER_ASSIGN: + return NSS_IF_BSHAPER_ASSIGN; + case NSS_QDISC_IF_SHAPER_UNASSIGN: + return NSS_IF_BSHAPER_UNASSIGN; + case NSS_QDISC_IF_SHAPER_CONFIG: + return NSS_IF_BSHAPER_CONFIG; + default: + nss_qdisc_info("Unknown message type for a bridge - type %d", msg_type); + return -1; + } + } else { + switch(msg_type) { + case NSS_QDISC_IF_SHAPER_ASSIGN: + return NSS_IF_ISHAPER_ASSIGN; + case NSS_QDISC_IF_SHAPER_UNASSIGN: + return NSS_IF_ISHAPER_UNASSIGN; + case NSS_QDISC_IF_SHAPER_CONFIG: + return NSS_IF_ISHAPER_CONFIG; + default: + nss_qdisc_info("Unknown message type for an interface - type %d", msg_type); + return -1; + } + } +} + +/* * nss_qdisc_attach_bshaper_callback() * Call back funtion for bridge shaper attach to an interface. */ @@ -609,6 +612,7 @@ static void nss_qdisc_root_cleanup_free_ nss_qdisc_info("Root qdisc %px (type %d) free SUCCESS - response " "type: %d\n", nq->qdisc, nq->type, nim->msg.shaper_configure.config.response_type); + nss_qdisc_root_cleanup_shaper_unassign(nq); } @@ -1162,15 +1166,8 @@ unsigned int nss_qdisc_drop(struct Qdisc */ void nss_qdisc_reset(struct Qdisc *sch) { - struct nss_qdisc *nq; - - if(!(sch->flags & TCQ_F_NSS)) { - qdisc_reset_queue(sch); - nss_qdisc_info("Qdisc %px resetting non NSS qdisc\n", sch); - return; - } + struct nss_qdisc *nq = qdisc_priv(sch); - nq = qdisc_priv(sch); nss_qdisc_info("Qdisc %px (type %d) resetting\n", sch, nq->type); @@ -1209,10 +1206,10 @@ static bool nss_qdisc_iterate_fl(struct return 0; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) - status = tc_classify(skb, tcf, &res, false); -#else +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) status = tcf_classify(skb, tcf, &res, false); +#else + status = tcf_classify(skb, NULL, tcf, &res, false); #endif if ((status == TC_ACT_STOLEN) || (status == TC_ACT_QUEUED)) { return 1; @@ -1892,7 +1889,6 @@ int nss_qdisc_configure(struct nss_qdisc return 0; } - /* * nss_qdisc_register_configure_callback() * Register shaper configure callback, which gets invoked on receiving a response. @@ -1949,11 +1945,6 @@ void nss_qdisc_destroy(struct nss_qdisc } /* - * Delete node from stats list - */ - nss_qdisc_stats_qdisc_detach(nq); - - /* * How we begin to tidy up depends on whether we are root or child */ nq->pending_final_state = NSS_QDISC_STATE_IDLE; @@ -1972,11 +1963,6 @@ void nss_qdisc_destroy(struct nss_qdisc } /* - * Stop stats polling - */ - nss_qdisc_stats_stop_polling(nq); - - /* * Begin by freeing the root shaper node */ nss_qdisc_root_cleanup_free_node(nq); @@ -2129,8 +2115,6 @@ int __nss_qdisc_init(struct Qdisc *sch, */ if ((sch->parent == TC_H_ROOT) && (!nq->is_class)) { nss_qdisc_info("Qdisc %px (type %d) is root\n", nq->qdisc, nq->type); - nss_qdisc_info("Qdisc %px dev-name %s qdisc_dev(sch)->qdisc %px, qdisc_dev(sch)->qdisc->handle %x\n", qdisc_dev(sch), qdisc_dev(sch)->name, qdisc_dev(sch)->qdisc, qdisc_dev(sch)->qdisc->handle); - nss_qdisc_info("Qdisc %px (sch %px) is root, sch->handle %x\n", nq->qdisc, sch, sch->handle); nq->is_root = true; root = sch; } else { @@ -2188,6 +2172,8 @@ int __nss_qdisc_init(struct Qdisc *sch, * This is to prevent mixing NSS and PPE qdisc with linux qdisc. */ if ((parent != TC_H_ROOT) && (root->ops->owner != THIS_MODULE)) { + nss_qdisc_warning("parent (%d) and TC_H_ROOT (%d))", parent, TC_H_ROOT); + nss_qdisc_warning("root->ops->owner (%px) and THIS_MODULE (%px))", root->ops->owner , THIS_MODULE); nss_qdisc_warning("NSS qdisc %px (type %d) used along with non-nss qdiscs," " or the interface is currently down", nq->qdisc, nq->type); } @@ -2288,11 +2274,6 @@ int __nss_qdisc_init(struct Qdisc *sch, * If state is positive, return success */ if (state > 0) { - - /* - * Qdisc successfully initialized, add it to stats list if its not a class - */ - nss_qdisc_stats_qdisc_attach(nq); return 0; } @@ -2460,15 +2441,6 @@ int __nss_qdisc_init(struct Qdisc *sch, goto init_fail; } #endif - /* - * Initialize the stats management only for root node - */ - if (!nss_qdisc_stats_sync_many_init(nq)) { - nss_qdisc_error("Qdisc %px (type %d) stats sync init failed", nq->qdisc, nq->type); - nss_shaper_unregister_shaping(nq->nss_shaping_ctx); - atomic_set(&nq->state, NSS_QDISC_STATE_INIT_FAILED); - goto init_fail; - } /* * Create and send the shaper assign message to the NSS interface @@ -2498,7 +2470,7 @@ int __nss_qdisc_init(struct Qdisc *sch, if (igs_put) { nss_igs_module_put(); } - nss_qdisc_error("init for qdisc %x timedout!\n", nq->qos_tag); + nss_qdisc_error("init for qdisc %x timedout!\n", nq->qos_tag); return -1; } @@ -2509,16 +2481,6 @@ int __nss_qdisc_init(struct Qdisc *sch, if (state > 0) { /* - * Qdisc successfully initialized add it to stats list if its not a class - */ - nss_qdisc_stats_qdisc_attach(nq); - - /* - * Root node is successfully configured, start stats polling - */ - nss_qdisc_stats_start_polling(nq); - - /* * Return if this is not a root qdisc on a bridge interface. */ if (!nq->is_root || !nq->is_bridge) { @@ -2559,14 +2521,6 @@ init_fail: } #endif - - /* - * Clean up stats sync objects if initialized. - */ - if (nq->stats_wq) { - nss_qdisc_stats_sync_many_exit(nq); - } - /* * Destroy any virtual interfaces created by us before returning a failure. */ @@ -2601,6 +2555,210 @@ int nss_qdisc_init(struct Qdisc *sch, st } /* + * nss_qdisc_basic_stats_callback() + * Invoked after getting basic stats + */ +static void nss_qdisc_basic_stats_callback(void *app_data, + struct nss_if_msg *nim) +{ + struct nss_qdisc *nq = (struct nss_qdisc *)app_data; + struct Qdisc *qdisc = nq->qdisc; + struct gnet_stats_basic_packed *bstats; + struct gnet_stats_queue *qstats; + struct nss_shaper_node_stats_response *response; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) + atomic_t *refcnt; +#else + refcount_t *refcnt; +#endif + + if (nim->cm.response != NSS_CMN_RESPONSE_ACK) { + nss_qdisc_warning("Qdisc %px (type %d): Receive stats FAILED - " + "response: type: %d\n", qdisc, nq->type, + nim->msg.shaper_configure.config.response_type); + atomic_sub(1, &nq->pending_stat_requests); + wake_up(&nq->wait_queue); + return; + } + + response = &nim->msg.shaper_configure.config.msg.shaper_node_stats_get.response; + + /* + * Get the right stats pointers based on whether it is a class + * or a qdisc. + */ + if (nq->is_class) { + bstats = &nq->bstats; + qstats = &nq->qstats; + refcnt = &nq->refcnt; + } else { + bstats = &qdisc->bstats; + qstats = &qdisc->qstats; + refcnt = &qdisc->refcnt; + qdisc->q.qlen = response->sn_stats.qlen_packets; + } + + /* + * Update qdisc->bstats + */ + spin_lock_bh(&nq->lock); + bstats->bytes += (__u64)response->sn_stats.delta.dequeued_bytes; + bstats->packets += response->sn_stats.delta.dequeued_packets; + + /* + * Update qdisc->qstats + */ + qstats->backlog = response->sn_stats.qlen_bytes; + + qstats->drops += (response->sn_stats.delta.enqueued_packets_dropped + + response->sn_stats.delta.dequeued_packets_dropped); + + /* + * Update qdisc->qstats + */ + qstats->qlen = response->sn_stats.qlen_packets; + qstats->requeues = 0; + qstats->overlimits += response->sn_stats.delta.queue_overrun; + spin_unlock_bh(&nq->lock); + + /* + * Shapers that maintain additional unique statistics will process them + * via a registered callback. So invoke if its been registered. + */ + if (nq->stats_cb) { + nq->stats_cb(nq, response); + } + + /* + * All access to nq fields below do not need lock protection. They + * do not get manipulated on different thread contexts. + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)) + if (atomic_read(refcnt) == 0) { +#else + if (refcount_read(refcnt) == 0) { +#endif + atomic_sub(1, &nq->pending_stat_requests); + wake_up(&nq->wait_queue); + return; + } + + /* + * Requests for stats again, after 1 sec. + */ + nq->stats_get_timer.expires += HZ; + if (nq->stats_get_timer.expires <= jiffies) { + nss_qdisc_info("losing time %lu, jiffies = %lu\n", + nq->stats_get_timer.expires, jiffies); + nq->stats_get_timer.expires = jiffies + HZ; + } + add_timer(&nq->stats_get_timer); +} + +/* + * nss_qdisc_get_stats_timer_callback() + * Invoked periodically to get updated stats + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) +static void nss_qdisc_get_stats_timer_callback(unsigned long int data) +#else +static void nss_qdisc_get_stats_timer_callback(struct timer_list *tm) +#endif +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) + struct nss_qdisc *nq = (struct nss_qdisc *)data; +#else + struct nss_qdisc *nq = from_timer(nq, tm, stats_get_timer); +#endif + + nss_tx_status_t rc; + struct nss_if_msg nim; + int msg_type; + + /* + * Create and send the shaper configure message to the NSS interface + */ + msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_CONFIG); + nss_qdisc_msg_init(&nim, nq->nss_interface_number, msg_type, sizeof(struct nss_if_shaper_configure), + nss_qdisc_basic_stats_callback, + nq); + nim.msg.shaper_configure.config.request_type = NSS_SHAPER_CONFIG_TYPE_SHAPER_NODE_BASIC_STATS_GET; + nim.msg.shaper_configure.config.msg.shaper_node_stats_get.qos_tag = nq->qos_tag; + rc = nss_if_tx_msg(nq->nss_shaping_ctx, &nim); + + /* + * Check if we failed to send the stats request to NSS. + */ + if (rc != NSS_TX_SUCCESS) { + nss_qdisc_info("%px: stats fetch request dropped, causing " + "delay in stats fetch\n", nq->qdisc); + + /* + * Schedule the timer once again for re-trying. Since this is a + * re-try we schedule it 100ms from now, instead of a whole second. + */ + nq->stats_get_timer.expires = jiffies + HZ/10; + add_timer(&nq->stats_get_timer); + } +} + +/* + * nss_qdisc_start_basic_stats_polling() + * Call to initiate the stats polling timer + */ +void nss_qdisc_start_basic_stats_polling(struct nss_qdisc *nq) +{ + /* + * In case the stats polling timer is already + * initiated, return. This can happen only when + * there is a fallback from PPE to NSS qdisc. + */ + if (atomic_read(&nq->pending_stat_requests)) { + return; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) + init_timer(&nq->stats_get_timer); + nq->stats_get_timer.function = nss_qdisc_get_stats_timer_callback; + nq->stats_get_timer.data = (unsigned long)nq; +#else + timer_setup(&nq->stats_get_timer, nss_qdisc_get_stats_timer_callback, 0); +#endif + + nq->stats_get_timer.expires = jiffies + HZ; + atomic_set(&nq->pending_stat_requests, 1); + add_timer(&nq->stats_get_timer); +} + +/* + * nss_qdisc_stop_basic_stats_polling() + * Call to stop polling of basic stats + */ +void nss_qdisc_stop_basic_stats_polling(struct nss_qdisc *nq) +{ + /* + * If the timer was active, then delete timer and return. + */ + if (del_timer(&nq->stats_get_timer) > 0) { + /* + * The timer was still active (counting down) when it was deleted. + * Therefore we are sure that there are no pending stats request + * for which we need to wait for. We can therefore return. + */ + return; + } + + /* + * The timer has already fired, which means we have a pending stat response. + * We will have to wait until we have received the pending response. + */ + if (!wait_event_timeout(nq->wait_queue, atomic_read(&nq->pending_stat_requests) == 0, + NSS_QDISC_COMMAND_TIMEOUT)) { + nss_qdisc_error("Stats request command for %x timedout!\n", nq->qos_tag); + } +} + +/* * nss_qdisc_gnet_stats_copy_basic() * Wrapper around gnet_stats_copy_basic() */ @@ -2876,10 +3034,6 @@ static int __init nss_qdisc_module_init( return ret; nss_qdisc_info("nss qdisc device notifiers registered\n"); - if (!nss_qdisc_stats_work_queue_init()) { - nss_qdisc_error("Failed to initialized stats workqueue thread\n"); - } - #if defined(NSS_QDISC_PPE_SUPPORT) nss_ppe_port_res_alloc(); nss_qdisc_info("nss ppe qdsic configured"); @@ -2899,8 +3053,6 @@ static void __exit nss_qdisc_module_exit } #endif - nss_qdisc_stats_work_queue_exit(); - unregister_qdisc(&nss_pfifo_qdisc_ops); nss_qdisc_info("nsspfifo unregistered\n"); --- a/nss_qdisc/nss_qdisc.h +++ b/nss_qdisc/nss_qdisc.h @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2018, 2020 The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -35,17 +35,12 @@ #if defined(NSS_QDISC_PPE_SUPPORT) #include "nss_ppe.h" #endif -#include "nss_qdisc_stats.h" -#include "nss_qdisc_htable.h" #define NSS_QDISC_DEBUG_LEVEL_ERROR 1 #define NSS_QDISC_DEBUG_LEVEL_WARN 2 #define NSS_QDISC_DEBUG_LEVEL_INFO 3 #define NSS_QDISC_DEBUG_LEVEL_TRACE 4 -#define NSS_QDISC_COMMAND_TIMEOUT (10*HZ) /* We set 10sec to be the command */ - /* timeout value for messages */ - /* * Debug message for module init and exit */ @@ -92,9 +87,6 @@ #endif #endif -#define NSS_QDISC_STATS_SYNC_MANY_PERIOD msecs_to_jiffies(1000) -#define NSS_QDISC_STATS_SYNC_MANY_UDELAY 5000 /* Delay for 5 ms */ - /* * State values */ @@ -144,27 +136,6 @@ struct nss_qdisc; typedef void (*nss_qdisc_stats_callback_t)(struct nss_qdisc *nq, struct nss_shaper_node_stats_response *response); typedef void (*nss_qdisc_configure_callback_t)(struct nss_qdisc *nq, struct nss_shaper_configure *response); - -/* - * Qdisc stats sync info object - */ -struct nss_qdisc_stats_wq { - struct nss_qdisc *nq; /* Pointer to root nss_qdisc */ - struct list_head stats_list; /* List head stats sync management work */ - struct nss_if_msg stats_sync_req_msg; /* FW sync message */ - struct timer_list stats_get_timer; /* Timer used to start fresh iter */ - unsigned long int next_req_time; /* Time at which next sync iteration starts */ - unsigned long int stats_request_success; /* Number of success stats request */ - unsigned long int stats_request_fail; /* Number of failed stats request */ - unsigned long int stats_request_nack; /* Number of NACK'd stats request */ - atomic_t pending_stat_work; /* Pending work queue status */ - atomic_t pending_stat_resp; /* Pending statistics response from FW */ - bool stats_polling_stopped; /* True when polling is stopped due to qdisc delete */ - wait_queue_head_t stats_work_waitqueue; /* Wait queue to wait on work queue processing */ - wait_queue_head_t stats_resp_waitqueue; /* Wait queue used to wait on response from the NSS */ - struct nss_qdisc_htable nqt; /* Struct to manage hash table of Qdiscs for stats */ -}; - struct nss_qdisc { struct Qdisc *qdisc; /* Handy pointer back to containing qdisc */ struct nss_qdisc *parent; /* Pointer to parent nss qdisc */ @@ -226,8 +197,6 @@ struct nss_qdisc { #endif struct timer_list stats_get_timer; /* Timer used to poll for stats */ atomic_t pending_stat_requests; /* Number of pending stats responses */ - struct nss_qdisc_stats_wq *stats_wq; /* Stats info and state work object */ - struct hlist_node hlist; /* Hlist node for managing stats hash list */ wait_queue_head_t wait_queue; /* Wait queue used to wait on responses from the NSS */ spinlock_t lock; /* Lock to protect the nss qdisc structure */ uint16_t mode; /* Mode of Qdisc/class */ @@ -460,6 +429,18 @@ extern int nss_qdisc_init(struct Qdisc * void *extack); /* + * nss_qdisc_start_basic_stats_polling() + * Call to initiate the stats polling timer + */ +extern void nss_qdisc_start_basic_stats_polling(struct nss_qdisc *nq); + +/* + * nss_qdisc_stop_basic_stats_polling() + * Call to stop polling of basic stats + */ +extern void nss_qdisc_stop_basic_stats_polling(struct nss_qdisc *nq); + +/* * nss_qdisc_gnet_stats_copy_basic() * Wrapper around gnet_stats_copy_basic() */ @@ -505,15 +486,3 @@ extern unsigned long nss_qdisc_tcf_bind( * Unbind the filter from the qdisc. */ extern void nss_qdisc_tcf_unbind(struct Qdisc *sch, unsigned long arg); - -/* - * nss_qdisc_get_interface_msg() - * Returns the correct message that needs to be sent down to the NSS interface. - */ -extern int nss_qdisc_get_interface_msg(bool is_bridge, uint32_t msg_type); - -/* - * nss_qdisc_msg_init() - * Initialize the qdisc specific message - */ -extern void nss_qdisc_msg_init(struct nss_if_msg *nim, uint16_t if_num, uint32_t msg_type, uint32_t len, nss_if_msg_callback_t cb, void *app_data); --- a/nss_qdisc/nss_tbl.c +++ b/nss_qdisc/nss_tbl.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2014-2017, 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, 2019-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -88,7 +88,12 @@ static void nss_tbl_destroy(struct Qdisc /* * Now we can destroy our child qdisc */ - nss_qdisc_put(q->qdisc); + nss_qdisc_put(q->qdisc); + + /* + * Stop the polling of basic stats and destroy qdisc. + */ + nss_qdisc_stop_basic_stats_polling(&q->nq); nss_qdisc_destroy(&q->nq); } @@ -287,6 +292,11 @@ static int nss_tbl_init(struct Qdisc *sc return -EINVAL; } + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(&q->nq); + return 0; } --- a/nss_qdisc/nss_wred.c +++ b/nss_qdisc/nss_wred.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2014-2017, 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, 2020 The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -108,6 +108,11 @@ static void nss_wred_destroy(struct Qdis { struct nss_qdisc *nq = (struct nss_qdisc *)qdisc_priv(sch); + /* + * Stop the polling of basic stats + */ + nss_qdisc_stop_basic_stats_polling(nq); + nss_qdisc_destroy(nq); nss_qdisc_info("nsswred destroyed"); } @@ -370,6 +375,11 @@ static int nss_wred_init(struct Qdisc *s return -EINVAL; } + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(nq); + return 0; } --- a/nss_qdisc/nss_wrr.c +++ b/nss_qdisc/nss_wrr.c @@ -1,13 +1,9 @@ /* ************************************************************************** - * Copyright (c) 2014-2017, 2019-2021, The Linux Foundation. All rights reserved. - * - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. - * + * Copyright (c) 2014-2017, 2019-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. - * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -91,6 +87,11 @@ static void nss_wrr_destroy_class(struct nss_qdisc_put(cl->qdisc); /* + * Stop the stats polling timer and free class + */ + nss_qdisc_stop_basic_stats_polling(&cl->nq); + + /* * Destroy the shaper in NSS */ nss_qdisc_destroy(&cl->nq); @@ -351,6 +352,11 @@ static int nss_wrr_change_class(struct Q */ qdisc_class_hash_grow(sch, &q->clhash); + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(&cl->nq); + nss_qdisc_info("Class %u successfully allocated\n", classid); } @@ -400,7 +406,11 @@ failure: return -EINVAL; } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)) +static int nss_wrr_delete_class(struct Qdisc *sch, unsigned long arg, struct netlink_ext_ack *extack) +#else static int nss_wrr_delete_class(struct Qdisc *sch, unsigned long arg) +#endif { struct nss_wrr_sched_data *q = qdisc_priv(sch); struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)arg; @@ -408,14 +418,11 @@ static int nss_wrr_delete_class(struct Q int refcnt; /* - * If the class is a root class or has a child qdisc attached - * we do not support deleting it. + * Since all classes are leaf nodes in our case, we dont have to make + * that check. */ - if ((cl == &q->root) || (cl->qdisc != &noop_qdisc)) { - nss_qdisc_warning("Cannot delete wrr class %x as it is the " - "root class or has a child qdisc attached\n", cl->nq.qos_tag); + if (cl == &q->root) return -EBUSY; - } /* * The message to NSS should be sent to the parent of this class @@ -429,24 +436,16 @@ static int nss_wrr_delete_class(struct Q } sch_tree_lock(sch); + qdisc_reset(cl->qdisc); qdisc_class_hash_remove(&q->clhash, &cl->cl_common); refcnt = nss_qdisc_atomic_sub_return(&cl->nq); sch_tree_unlock(sch); - - /* - * For 5.4 and above kernels, calling nss_htb_destroy_class - * explicitly as there is no put_class which would have called - * nss_wrr_destroy_class when refcnt becomes zero. - */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) - nss_wrr_destroy_class(sch, cl); -#else if (!refcnt) { nss_qdisc_error("Reference count should not be zero for class %px\n", cl); } -#endif + return 0; } @@ -722,6 +721,11 @@ static int nss_wrr_init_qdisc(struct Qdi nss_qdisc_info("Nsswrr initialized - handle %x parent %x\n", sch->handle, sch->parent); + /* + * Start the stats polling timer + */ + nss_qdisc_start_basic_stats_polling(&q->nq); + return 0; } @@ -760,11 +764,6 @@ static int nss_wrr_change_qdisc(struct Q static void nss_wrr_reset_class(struct nss_wrr_class_data *cl) { - if (cl->qdisc == &noop_qdisc) { - nss_qdisc_trace("Class %x has no child qdisc to reset\n", cl->nq.qos_tag); - return; - } - nss_qdisc_reset(cl->qdisc); nss_qdisc_info("Nsswrr class resetted %px\n", cl->qdisc); } @@ -837,6 +836,11 @@ static void nss_wrr_destroy_qdisc(struct qdisc_class_hash_destroy(&q->clhash); /* + * Stop the polling of basic stats + */ + nss_qdisc_stop_basic_stats_polling(&q->nq); + + /* * Now we can go ahead and destroy the qdisc. * Note: We dont have to detach ourself from our parent because this * will be taken care of by the graft call. --- a/openvpn/plugins/Makefile +++ b/openvpn/plugins/Makefile @@ -1,12 +1,11 @@ # Makefile for the ovpn plugins -ccflags-y := $(NSS_CCFLAGS) -I$(obj) -I$(obj)/../../exports -I$(obj)/include -I$(obj)/../src -I$(STAGING_DIR)/usr/include/qca-nss-ecm - +ccflags-y := $(NSS_CCFLAGS) -I$(obj) -I$(obj)/../../exports -I$(obj)/include -I$(obj)/../src ccflags-y += -DNSS_CLIENT_BUILD_ID="$(BUILD_ID)" ccflags-y += -DNSS_OVPNMGR_DEBUG_LEVEL=0 ccflags-y += -DNSS_OVPN_LINK_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-ovpn-link.o qca-nss-ovpn-link-objs := nss_ovpn_link.o --- a/openvpn/plugins/nss_ovpn_sk.c +++ b/openvpn/plugins/nss_ovpn_sk.c @@ -19,7 +19,6 @@ * Socket implementation for OVPN. */ -#include #include #include #include @@ -264,12 +263,7 @@ static int nss_ovpn_sk_update_ipv6_tuple struct rt6_info *rt6; int addr_type; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) rt6 = rt6_lookup(dev_net(pinfo->dev), (struct in6_addr *)tun_data->tun_hdr.dst_ip, NULL, 0, 0); -#else - rt6 = rt6_lookup(dev_net(pinfo->dev), (struct in6_addr *)tun_data->tun_hdr.dst_ip, NULL, 0, 0, 0); -#endif - if (!rt6) { nss_ovpn_sk_warn("%px: Failed to find IPv6 route.\n", pinfo); return -EINVAL; @@ -411,11 +405,7 @@ static int nss_ovpn_sk_tun_add(struct so * Bring up tunnel device. */ rtnl_lock(); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) err = dev_open(tun_dev); -#else - err = dev_open(tun_dev, NULL); -#endif rtnl_unlock(); if (err) { @@ -642,11 +632,11 @@ static int nss_ovpn_sk_sendmsg(struct so */ static int nss_ovpn_sk_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags) { - struct nss_ovpn_sk_pkt_info *pkt_info_data, pkt_data; + struct nss_ovpn_sk_pkt_info *pkt_info_data; struct nss_ovpnmgr_metadata pkt_info; int copied, ret; struct sk_buff *skb; - struct cmsghdr *cmsg, k_cmsg; + struct cmsghdr *cmsg; struct sock *sk = sock->sk; if (flags & ~(MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC | MSG_CMSG_COMPAT)) { @@ -666,13 +656,6 @@ static int nss_ovpn_sk_recvmsg(struct so return -EINVAL; } - if (copy_from_user(&k_cmsg, cmsg, sizeof(struct cmsghdr))) { - nss_ovpn_sk_warn("Copy from user failed\n"); - return -EINVAL; - } - - cmsg = &k_cmsg; - if (!CMSG_OK(msg, cmsg)) { nss_ovpn_sk_warn("%px: Incorrect message format\n", sock); return -EINVAL; @@ -700,15 +683,8 @@ static int nss_ovpn_sk_recvmsg(struct so * Send control information to application. */ memcpy(&pkt_info, skb->cb, sizeof(pkt_info)); - - pkt_data.tunnel_id = pkt_info.tunnel_id; - pkt_data.flags = pkt_info.flags; - - if (copy_to_user(pkt_info_data, &pkt_data, sizeof(pkt_data))) { - nss_ovpn_sk_warn("Copy from user failed\n"); - return -EINVAL; - } - + pkt_info_data->tunnel_id = pkt_info.tunnel_id; + pkt_info_data->flags = pkt_info.flags; put_cmsg(msg, SOL_IP, IP_PKTINFO, sizeof(*pkt_info_data), pkt_info_data); copied = skb->len; @@ -864,12 +840,7 @@ int nss_ovpn_sk_send(struct sk_buff *skb * for indefinite time. */ skb_orphan(skb); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) nf_reset(skb); -#else - nf_reset_ct(skb); -#endif /* Enqueue packet */ if (sock_queue_rcv_skb(sk, skb) < 0) { --- a/openvpn/src/Makefile +++ b/openvpn/src/Makefile @@ -3,7 +3,7 @@ ccflags-y := $(NSS_CCFLAGS) -I$(obj) -I$(obj)/../../exports -I$(obj)/include -I$(obj)/../plugins ccflags-y += -DNSS_CLIENT_BUILD_ID="$(BUILD_ID)" ccflags-y += -DNSS_OVPNMGR_DEBUG_LEVEL=0 -DNSS_OVPNMGR_DEBUG_ENABLE_PKT_DUMP=0 -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-ovpn-mgr.o qca-nss-ovpn-mgr-objs := nss_ovpnmgr.o nss_ovpnmgr_app.o nss_ovpnmgr_tun.o nss_ovpnmgr_crypto.o \ --- a/openvpn/src/nss_ovpnmgr.c +++ b/openvpn/src/nss_ovpnmgr.c @@ -99,12 +99,7 @@ static int nss_ovpnmgr_netdevice_event(s */ read_unlock_bh(&ovpnmgr_ctx.lock); if (event == NETDEV_UP) { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)) dev_open(nss_dev); -#else - dev_open(nss_dev, NULL); -#endif - } else { dev_close(nss_dev); } --- a/openvpn/src/nss_ovpnmgr_app.c +++ b/openvpn/src/nss_ovpnmgr_app.c @@ -62,12 +62,7 @@ static struct net_device *nss_ovpnmgr_ap return dev; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) rt6 = rt6_lookup(&init_net, (const struct in6_addr *)rt->ip_addr, NULL, 0, 0); -#else - rt6 = rt6_lookup(&init_net, (const struct in6_addr *)rt->ip_addr, NULL, 0, 0, 0); -#endif - if (!rt6) { return NULL; } --- a/openvpn/src/nss_ovpnmgr_route.c +++ b/openvpn/src/nss_ovpnmgr_route.c @@ -80,7 +80,7 @@ int nss_ovpnmgr_route_set_active(struct /* * This API should be called under lock. */ - lockdep_assert_held(&ovpnmgr_ctx.lock); + BUG_ON(write_can_lock(&ovpnmgr_ctx.lock)); /* * Search for route entry with from_addr. --- a/openvpn/src/nss_ovpnmgr_tun.c +++ b/openvpn/src/nss_ovpnmgr_tun.c @@ -130,11 +130,7 @@ static void nss_ovpnmgr_tun_ipv6_forward skb->protocol = htons(ETH_P_IPV6); ip6h = ipv6_hdr(skb); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) rt6 = rt6_lookup(dev_net(app->dev), &ip6h->daddr, &ip6h->saddr, 0, 0); -#else - rt6 = rt6_lookup(dev_net(app->dev), &ip6h->daddr, &ip6h->saddr, 0, 0, 0); -#endif if (!rt6) { nss_ovpnmgr_warn("%px: Failed to find IPv6 route.\n", skb); tun->outer.stats.host_pkt_drop++; @@ -488,11 +484,7 @@ static void nss_ovpnmgr_tun_dev_setup(st dev->header_ops = NULL; dev->netdev_ops = &ovpnmgr_dev_ops; dev->ethtool_ops = NULL; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 8)) dev->destructor = nss_ovpnmgr_tun_free; -#else - dev->priv_destructor = nss_ovpnmgr_tun_free; -#endif } /* --- a/portifmgr/Makefile +++ b/portifmgr/Makefile @@ -11,4 +11,4 @@ obj-m += qca-nss-portifmgr.o qca-nss-portifmgr-objs := nss_portifmgr.o ccflags-y += -DNSS_PORTIFMGR_DEBUG_LEVEL=2 #-DNSS_PORTIFMGR_REF_AP148 -ccflags-y += -Wall -Werror +ccflags-y += -Werror \ No newline at end of file --- a/portifmgr/nss_portifmgr.c +++ b/portifmgr/nss_portifmgr.c @@ -187,16 +187,20 @@ drop: } /* - * nss_portifmgr_get_stats() + * nss_portifmgr_get_stats64() * Netdev get stats function to get port stats */ -static struct rtnl_link_stats64 *nss_portifmgr_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) +/* + * nss_nlgre_redir_cmn_dev_stats64 + * Report packet statistics to linux + */ +static void nss_portifmgr_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) { struct nss_portifmgr_priv *priv = (struct nss_portifmgr_priv *)netdev_priv(dev); BUG_ON(priv == NULL); nss_portid_get_stats(priv->if_num, stats); - return stats; } /* @@ -225,7 +229,7 @@ static const struct net_device_ops nss_p .ndo_start_xmit = nss_portifmgr_start_xmit, .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = nss_portifmgr_change_mtu, - .ndo_get_stats64 = nss_portifmgr_get_stats, + .ndo_get_stats64 = nss_portifmgr_get_stats64, }; /* --- a/pppoe/Makefile +++ b/pppoe/Makefile @@ -1,10 +1,12 @@ # Makefile for pppoe client ccflags-y += -I$(obj)/../exports -I$(obj)/.. -I$(obj)/nss_hal/include ccflags-y += -DNSS_PPPOE_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-pppoe.o qca-nss-pppoe-objs := nss_connmgr_pppoe.o ifneq (,$(filter $(CONFIG_BONDING),y m)) +ifneq ($(findstring 4.4, $(KERNELVERSION)),) ccflags-y += -DBONDING_SUPPORT endif +endif --- a/pppoe/nss_connmgr_pppoe.c +++ b/pppoe/nss_connmgr_pppoe.c @@ -69,11 +69,7 @@ static int nss_connmgr_pppoe_get_session return -1; } - if (pppoe_channel_addressing_get(channel[0], addressing)) { - nss_connmgr_pppoe_warn("%px: failed to get addressing information\n", dev); - ppp_release_channels(channel, 1); - return -1; - } + pppoe_channel_addressing_get(channel[0], addressing); dev_put(addressing->dev); ppp_release_channels(channel, 1); --- a/pptp/Makefile +++ b/pptp/Makefile @@ -1,6 +1,6 @@ # Makefile for pptp client ccflags-y += -I$(obj)/../exports -I$(obj)/.. -I$(obj)/nss_hal/include ccflags-y += -DNSS_PPTP_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-pptp.o qca-nss-pptp-objs := nss_connmgr_pptp.o --- a/pptp/nss_connmgr_pptp.c +++ b/pptp/nss_connmgr_pptp.c @@ -156,11 +156,6 @@ static int nss_connmgr_pptp_get_session( return -1; } - if (ppp_is_cp_enabled(dev)) { - nss_connmgr_pptp_warning("%px: rx or tx compression is enabled for PPP\n", dev); - return -1; - } - ppp_ch_count = ppp_hold_channels(dev, channel, 1); nss_connmgr_pptp_info("%px: PPP hold channel ret %d\n", dev, ppp_ch_count); if (ppp_ch_count != 1) { --- a/profiler/Makefile +++ b/profiler/Makefile @@ -1,5 +1,5 @@ ccflags-y := -I$(obj) -I$(obj)/.. -I$(obj)/../exports -DNSS_DEBUG_LEVEL=0 #-DPROFILE_DEBUG -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-profile-drv.o qca-nss-profile-drv-objs := profile.o --- a/profiler/profile.c +++ b/profiler/profile.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -937,12 +938,26 @@ static ssize_t debug_if(struct file *fil return count; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +#define HAVE_PROC_OPS +#endif + +#ifdef HAVE_PROC_OPS +static const struct proc_ops profile_fops = { + .proc_open = profile_open, + .proc_read = profile_read, + .proc_lseek = seq_lseek, + .proc_release = profile_release, + .proc_write = debug_if, +}; +#else static const struct file_operations profile_fops = { .open = profile_open, .read = profile_read, .release = profile_release, .write = debug_if, }; +#endif /* * showing sample status on Linux console @@ -971,6 +986,15 @@ static ssize_t profile_rate_write(struct return 0; } +#ifdef HAVE_PROC_OPS +static const struct proc_ops profile_rate_fops = { + .proc_open = profile_rate_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = profile_rate_write, +}; +#else static const struct file_operations profile_rate_fops = { .open = profile_rate_open, .read = seq_read, @@ -978,6 +1002,7 @@ static const struct file_operations prof .release = single_release, .write = profile_rate_write, }; +#endif /* * hexdump @@ -1269,25 +1294,15 @@ void netap_profile_release_resource(void remove_proc_entry("rate", pdir); remove_proc_entry("data", pdir); remove_proc_entry("data1", pdir); - proc_remove(pdir); - pdir = NULL; - } - - if (node[0]->ctx) { - nss_profile_dma_deregister_cb(node[0]->ctx, 0); - if (node[1] && node[1]->ctx) { - nss_profile_dma_deregister_cb(node[1]->ctx, 0); - nss_profiler_release_dma(node[1]->ctx); - /* - * node[1] memory is part of node[0] allocation; same as the ccl. - */ - node[1] = NULL; - } - nss_profiler_release_dma(node[0]->ctx); } + nss_profile_dma_deregister_cb(node[0]->ctx, 0); + nss_profile_dma_deregister_cb(node[1]->ctx, 0); + nss_profiler_release_dma(node[1]->ctx); + nss_profiler_release_dma(node[0]->ctx); kfree(node[0]->ccl); kfree(node[0]); node[0] = NULL; + } /* --- a/tls/Makefile +++ b/tls/Makefile @@ -4,7 +4,7 @@ ccflags-y += $(NSS_CCFLAGS) -I$(obj)/../ #ccflags-y += -DNSS_TLSMGR_DEBUG_DUMP ccflags-y += -DNSS_TLSMGR_DEBUG_LEVEL=3 ccflags-y += -DNSS_TLSMGR_BUILD_ID=\"'Build_ID - $(shell date +'%m/%d/%y, %H:%M:%S') SoC=$(SoC)'\" -ccflags-y += -Wall -Werror +ccflags-y += -Werror obj-m += qca-nss-tlsmgr.o qca-nss-tlsmgr-objs += nss_tlsmgr.o --- a/tls/nss_tlsmgr_buf.c +++ b/tls/nss_tlsmgr_buf.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2020, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -52,15 +52,6 @@ #define NSS_TLSMGR_REC_MAX_SIZE (sizeof(struct nss_tlsmgr_rec) * NSS_TLSMGR_MDATA_REC_MAX) /* - * nss_tlsmgr_buf_get_rec_start() - * Get record start - */ -struct nss_tlsmgr_rec *nss_tlsmgr_buf_get_rec_start(struct nss_tlsmgr_buf *buf) -{ - return (struct nss_tlsmgr_rec *)((uint8_t *)buf + sizeof(*buf)); -} - -/* * nss_tlsmgr_buf_set_rec() * Reserve space for a record in a buffer. */ @@ -181,7 +172,7 @@ EXPORT_SYMBOL(nss_tlsmgr_buf_encap); */ nss_tlsmgr_status_t nss_tlsmgr_buf_decap(struct nss_tlsmgr_buf *buf, nss_tlsmgr_data_callback_t cb, void *app_data) { - struct nss_tlsmgr_tun *tun = buf->tun; + struct nss_tlsmgr_tun *tun; struct nss_tlsmgr_ctx *ctx; struct sk_buff *skb; struct nss_tlsmgr_rec *rec; @@ -216,6 +207,7 @@ nss_tlsmgr_status_t nss_tlsmgr_buf_decap skb = buf->skb; skb_pull(skb, mdata_start - skb->data); + tun = buf->tun; ctx = &tun->ctx_dec; return nss_tlsmgr_ctx_tx(ctx, skb, rec); --- a/tls/nss_tlsmgr_buf.h +++ b/tls/nss_tlsmgr_buf.h @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2020, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -41,6 +41,13 @@ struct nss_tlsmgr_buf { void nss_tlsmgr_buf_rx(struct nss_tlsmgr_buf *buf, nss_tlsmgr_status_t status); -struct nss_tlsmgr_rec *nss_tlsmgr_buf_get_rec_start(struct nss_tlsmgr_buf *buf); +/* + * nss_tlsmgr_buf_get_rec_start() + * Get record start + */ +static struct nss_tlsmgr_rec *nss_tlsmgr_buf_get_rec_start(struct nss_tlsmgr_buf *buf) +{ + return (struct nss_tlsmgr_rec *)((uint8_t *)buf + sizeof(*buf)); +} #endif /* !__NSS_TLSMGR_BUF_H_ */ --- a/tls/nss_tlsmgr_tun.c +++ b/tls/nss_tlsmgr_tun.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2020, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -102,7 +102,7 @@ static int nss_tlsmgr_tun_open(struct ne * nss_tlsmgr_tun_stats64() * TLS manager tunnel device */ -static struct rtnl_link_stats64 *nss_tlsmgr_get_tun_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) +void nss_tlsmgr_tun_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { struct nss_tlsmgr_tun *tun = netdev_priv(dev); @@ -113,29 +113,8 @@ static struct rtnl_link_stats64 *nss_tls nss_tlsmgr_ctx_stats_copy(&tun->ctx_dec, stats); read_unlock_bh(&tun->lock); - return stats; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) -/* - * nss_tlsmgr_tun_stats64() - * Netdev ops function to retrieve stats for kernel version < 4.6 - */ -static struct rtnl_link_stats64 *nss_tlsmgr_tun_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) -{ - return nss_tlsmgr_get_tun_stats64(dev, stats); -} -#else -/* - * nss_tlsmgr_tun_stats64() - * Netdev ops function to retrieve stats for kernel version >= 4.6 - */ -static void nss_tlsmgr_tun_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) -{ - nss_tlsmgr_get_tun_stats64(dev, stats); -} -#endif - /* * nss_tlsmgr_tun_change_mtu() * Change MTU size of TLS context device. @@ -211,22 +190,13 @@ static void nss_tlsmgr_tun_free_work(str read_unlock_bh(&tun->lock); } - /* * nss_tlsmgr_notify_event() * TLS manager notification timer handler */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) static void nss_tlsmgr_notify_event(unsigned long data) -#else -static void nss_tlsmgr_notify_event(struct timer_list *tm) -#endif { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) struct nss_tlsmgr_tun *tun = (struct nss_tlsmgr_tun *)data; -#else - struct nss_tlsmgr_tun *tun = from_timer(tun, tm, notify.timer); -#endif nss_tlsmgr_notify_callback_t cb; struct nss_tlsmgr_stats stats; void *app_data; @@ -248,17 +218,9 @@ static void nss_tlsmgr_notify_event(stru * nss_tlsmgr_notify_decongestion() * TLS manager decongestion notification */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) static void nss_tlsmgr_notify_decongestion(unsigned long data) -#else -static void nss_tlsmgr_notify_decongestion(struct timer_list *tm) -#endif { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) struct nss_tlsmgr_tun *tun = (struct nss_tlsmgr_tun *)data; -#else - struct nss_tlsmgr_tun *tun = from_timer(tun, tm, notify.timer); -#endif nss_tlsmgr_decongest_callback_t cb; void *app_data; @@ -393,7 +355,6 @@ struct net_device *nss_tlsmgr_tun_add(ns /* * Initialize Event notification and Decongestion timer */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) init_timer(&tun->notify.timer); tun->notify.timer.function = nss_tlsmgr_notify_event; tun->notify.timer.data = (unsigned long)tun; @@ -401,10 +362,6 @@ struct net_device *nss_tlsmgr_tun_add(ns init_timer(&tun->decongest.timer); tun->decongest.timer.function = nss_tlsmgr_notify_decongestion; tun->decongest.timer.data = (unsigned long)tun; -#else - timer_setup(&tun->notify.timer, nss_tlsmgr_notify_event, 0); - timer_setup(&tun->decongest.timer, nss_tlsmgr_notify_decongestion, 0); -#endif INIT_LIST_HEAD(&tun->free_list); INIT_WORK(&tun->free_work, nss_tlsmgr_tun_free_work); --- a/tunipip6/Makefile +++ b/tunipip6/Makefile @@ -2,7 +2,6 @@ ccflags-y += -I$(obj)/../exports -I$(obj)/.. ccflags-y += -DNSS_CLIENT_BUILD_ID="$(BUILD_ID)" ccflags-y += -DNSS_TUNIPIP6_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror obj-m += qca-nss-tunipip6.o qca-nss-tunipip6-objs := nss_connmgr_tunipip6.o nss_connmgr_tunipip6_sysctl.o nss_connmgr_tunipip6_stats.o ifneq ($(findstring 4.4, $(KERNELVERSION)),) --- a/tunipip6/nss_connmgr_tunipip6.c +++ b/tunipip6/nss_connmgr_tunipip6.c @@ -194,7 +194,6 @@ static void nss_tunipip6_encap_exception skb->pkt_type = PACKET_HOST; skb->skb_iif = dev->ifindex; skb->ip_summed = CHECKSUM_NONE; - ip_rt_put(rt); netif_receive_skb(skb); return; } @@ -348,7 +347,7 @@ static void nss_tunipip6_update_dev_stat { struct pcpu_sw_netstats stats; enum nss_dynamic_interface_type interface_type; - struct nss_tunipip6_stats_sync_msg *sync_stats = (struct nss_tunipip6_stats_sync_msg *)&tnlmsg->msg.stats; + struct nss_tunipip6_stats_sync_msg *sync_stats = (struct nss_tunipip6_stats_sync_msg *)&tnlmsg->msg.stats_sync; interface_type = nss_dynamic_interface_get_type(nss_tunipip6_get_context(), tnlmsg->cm.interface); @@ -381,7 +380,7 @@ void nss_tunipip6_event_receive(void *if netdev = (struct net_device *)if_ctx; switch (tnlmsg->cm.type) { - case NSS_TUNIPIP6_STATS_SYNC: + case NSS_TUNIPIP6_RX_STATS_SYNC: /* * Update netdevice statistics. */ @@ -627,7 +626,6 @@ configure_tunnel: tnlcreate->ttl_inherit = tnlcfg->ttl_inherit; tnlcreate->tos_inherit = tnlcfg->tos_inherit; tnlcreate->frag_id_update = tnlcfg->frag_id_update; - tnlcreate->fmr_max = tnlcfg->fmr_max; /* * Set "draft03" based on "tunnel_type". draft03 should be --- a/tunipip6/nss_connmgr_tunipip6_stats.c +++ b/tunipip6/nss_connmgr_tunipip6_stats.c @@ -132,7 +132,7 @@ static void nss_tunipip6_stats_update(ui void nss_tunipip6_stats_sync(struct net_device *dev, struct nss_tunipip6_msg *ntm) { uint32_t ifnum = ntm->cm.interface; - struct nss_tunipip6_stats_sync_msg *stats = &ntm->msg.stats; + struct nss_tunipip6_stats_sync_msg *stats = &ntm->msg.stats_sync; struct nss_tunipip6_instance *ntii; struct nss_tunipip6_stats *s; @@ -147,7 +147,6 @@ void nss_tunipip6_stats_sync(struct net_ s = &ntii->stats; if (ntii->inner_ifnum == ifnum) { nss_tunipip6_stats_update(s->inner_stats, stats); - s->inner_stats[NSS_TUNIPIP6_STATS_CONFIG_ENCAP_TOTAL_FMR] = stats->tun_stats.encap.cfg.total_fmr; } else if (ntii->outer_ifnum == ifnum) { nss_tunipip6_stats_update(s->outer_stats, stats); } else { --- a/vlan/Makefile +++ b/vlan/Makefile @@ -8,8 +8,8 @@ ifeq ($(SoC),$(filter $(SoC),ipq807x ipq ccflags-y += -DNSS_VLAN_MGR_PPE_SUPPORT endif -ccflags-y += -DNSS_VLAN_MGR_DEBUG_LEVEL=0 -ccflags-y += -Wall -Werror +ccflags-y += -DNSS_VLAN_MGR_DEBUG_LEVEL=4 +ccflags-y += -Werror ifneq (,$(filter $(CONFIG_BONDING),y m)) ccflags-y += -DBONDING_SUPPORT --- a/vlan/nss_vlan_mgr.c +++ b/vlan/nss_vlan_mgr.c @@ -1,12 +1,9 @@ /* ************************************************************************** * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. - * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. - * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -368,16 +365,22 @@ static void nss_vlan_mgr_port_role_event * nss_vlan_mgr_bond_configure_ppe() * Configure PPE for bond device */ -static int nss_vlan_mgr_bond_configure_ppe(struct nss_vlan_pvt *v, struct net_device *bond_dev, uint32_t vsi) +static int nss_vlan_mgr_bond_configure_ppe(struct nss_vlan_pvt *v, struct net_device *bond_dev) { + uint32_t vsi; int ret = 0; struct net_device *slave; int32_t port; int vlan_mgr_bond_port_role = -1; + if (ppe_vsi_alloc(NSS_VLAN_MGR_SWITCH_ID, &vsi)) { + nss_vlan_mgr_warn("%s: failed to allocate VSI for bond vlan device", bond_dev->name); + return -1; + } + if (nss_vlan_tx_vsi_attach_msg(v->nss_if, vsi) != NSS_TX_SUCCESS) { nss_vlan_mgr_warn("%s: failed to attach VSI to bond vlan interface\n", bond_dev->name); - return -1; + goto free_vsi; } /* @@ -390,7 +393,7 @@ static int nss_vlan_mgr_bond_configure_p if (!NSS_VLAN_PHY_PORT_CHK(port)) { rcu_read_unlock(); nss_vlan_mgr_warn("%s: %d is not valid physical port\n", slave->name, port); - return -1; + goto free_vsi; } /* @@ -406,7 +409,7 @@ static int nss_vlan_mgr_bond_configure_p * In case the bond interface has no slaves, we do not want to proceed further */ if (vlan_mgr_bond_port_role == -1) { - return -1; + goto free_vsi; } /* @@ -510,6 +513,7 @@ static int nss_vlan_mgr_bond_configure_p ret = NSS_VLAN_PORT_ROLE_CHANGED; } + v->ppe_vsi = vsi; return ret; delete_egress_rule: @@ -541,19 +545,30 @@ detach_vsi: nss_vlan_mgr_warn("%px: Failed to detach vsi %d\n", v, vsi); } +free_vsi: + if (ppe_vsi_free(NSS_VLAN_MGR_SWITCH_ID, vsi)) { + nss_vlan_mgr_warn("%px: Failed to free VLAN VSI\n", v); + } + return -1; } /* * nss_vlan_mgr_configure_ppe() * Configure PPE for physical devices */ -static int nss_vlan_mgr_configure_ppe(struct nss_vlan_pvt *v, struct net_device *dev, uint32_t vsi) +static int nss_vlan_mgr_configure_ppe(struct nss_vlan_pvt *v, struct net_device *dev) { + uint32_t vsi; int ret = 0; + if (ppe_vsi_alloc(NSS_VLAN_MGR_SWITCH_ID, &vsi)) { + nss_vlan_mgr_warn("%s: failed to allocate VSI for vlan device", dev->name); + return -1; + } + if (nss_vlan_tx_vsi_attach_msg(v->nss_if, vsi) != NSS_TX_SUCCESS) { nss_vlan_mgr_warn("%s: failed to attach VSI to vlan interface\n", dev->name); - return -1; + goto free_vsi; } /* @@ -637,6 +652,7 @@ static int nss_vlan_mgr_configure_ppe(st ret = NSS_VLAN_PORT_ROLE_CHANGED; } + v->ppe_vsi = vsi; return ret; delete_egress_rule: @@ -658,6 +674,11 @@ detach_vsi: nss_vlan_mgr_warn("%px: Failed to detach vsi %d\n", v, vsi); } +free_vsi: + if (ppe_vsi_free(NSS_VLAN_MGR_SWITCH_ID, vsi)) { + nss_vlan_mgr_warn("%px: Failed to free VLAN VSI\n", v); + } + return -1; } #endif @@ -800,8 +821,10 @@ static struct nss_vlan_pvt *nss_vlan_mgr */ static void nss_vlan_mgr_instance_free(struct nss_vlan_pvt *v) { +#ifdef NSS_VLAN_MGR_PPE_SUPPORT int32_t i; int ret = 0; +#endif spin_lock(&vlan_mgr_ctx.lock); BUG_ON(--v->refs); @@ -847,8 +870,7 @@ static void nss_vlan_mgr_instance_free(s } /* - * We will always have a VSI since this is allocated in beginning - * of the code. + * Free PPE VSI */ if (ppe_vsi_free(NSS_VLAN_MGR_SWITCH_ID, v->ppe_vsi)) { nss_vlan_mgr_warn("%px: Failed to free VLAN VSI\n", v); @@ -957,12 +979,14 @@ static int nss_vlan_mgr_register_event(s struct nss_vlan_pvt *v; int if_num; #ifdef NSS_VLAN_MGR_PPE_SUPPORT - uint32_t vsi; int ret; #endif uint32_t vlan_tag; +#ifdef NSS_VLAN_MGR_PPE_SUPPORT struct net_device *slave; - int32_t port, port_if; + int32_t port; +#endif + int32_t port_if; struct vlan_dev_priv *vlan; struct net_device *real_dev; bool is_bond_master = false; @@ -971,25 +995,19 @@ static int nss_vlan_mgr_register_event(s if (!v) return NOTIFY_DONE; - /* - * Allocate the VSI here. - */ -#ifdef NSS_VLAN_MGR_PPE_SUPPORT - if (ppe_vsi_alloc(NSS_VLAN_MGR_SWITCH_ID, &vsi)) { - nss_vlan_mgr_warn("%s: failed to allocate VSI for vlan device", dev->name); - return NOTIFY_DONE; - } -#endif - if_num = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_VLAN); if (if_num < 0) { nss_vlan_mgr_warn("%s: failed to alloc NSS dynamic interface\n", dev->name); - goto vsi_alloc_free; + nss_vlan_mgr_instance_free(v); + return NOTIFY_DONE; } if (!nss_register_vlan_if(if_num, NULL, dev, 0, v)) { nss_vlan_mgr_warn("%s: failed to register NSS dynamic interface", dev->name); - goto free_dynamic_interface; + if (nss_dynamic_interface_dealloc_node(if_num, NSS_DYNAMIC_INTERFACE_TYPE_VLAN) != NSS_TX_SUCCESS) + nss_vlan_mgr_warn("%px: Failed to dealloc vlan dynamic interface\n", v); + nss_vlan_mgr_instance_free(v); + return NOTIFY_DONE; } v->nss_if = if_num; @@ -1003,25 +1021,26 @@ static int nss_vlan_mgr_register_event(s #ifdef NSS_VLAN_MGR_PPE_SUPPORT if (!is_bond_master) - ret = nss_vlan_mgr_configure_ppe(v, dev, vsi); + ret = nss_vlan_mgr_configure_ppe(v, dev); else - ret = nss_vlan_mgr_bond_configure_ppe(v, real_dev, vsi); + ret = nss_vlan_mgr_bond_configure_ppe(v, real_dev); if (ret < 0) { - goto vlan_instance_free; + nss_vlan_mgr_instance_free(v); + return NOTIFY_DONE; } - - v->ppe_vsi = vsi; #endif if (nss_vlan_tx_set_mac_addr_msg(v->nss_if, v->dev_addr) != NSS_TX_SUCCESS) { nss_vlan_mgr_warn("%s: failed to set mac_addr msg\n", dev->name); - goto vlan_instance_free; + nss_vlan_mgr_instance_free(v); + return NOTIFY_DONE; } if (nss_vlan_tx_set_mtu_msg(v->nss_if, v->mtu) != NSS_TX_SUCCESS) { nss_vlan_mgr_warn("%s: failed to set mtu msg\n", dev->name); - goto vlan_instance_free; + nss_vlan_mgr_instance_free(v); + return NOTIFY_DONE; } vlan_tag = (v->tpid << NSS_VLAN_TPID_SHIFT | v->vid); @@ -1030,7 +1049,8 @@ static int nss_vlan_mgr_register_event(s (v->parent ? v->parent->nss_if : port_if), port_if) != NSS_TX_SUCCESS) { nss_vlan_mgr_warn("%s: failed to add vlan in nss\n", dev->name); - goto vlan_instance_free; + nss_vlan_mgr_instance_free(v); + return NOTIFY_DONE; } spin_lock(&vlan_mgr_ctx.lock); @@ -1058,21 +1078,6 @@ static int nss_vlan_mgr_register_event(s } #endif return NOTIFY_DONE; - -free_dynamic_interface: - if (nss_dynamic_interface_dealloc_node(if_num, NSS_DYNAMIC_INTERFACE_TYPE_VLAN) != NSS_TX_SUCCESS) - nss_vlan_mgr_warn("%px: Failed to dealloc vlan dynamic interface\n", v); - -vsi_alloc_free: -#ifdef NSS_VLAN_MGR_PPE_SUPPORT - if (ppe_vsi_free(NSS_VLAN_MGR_SWITCH_ID, v->ppe_vsi)) { - nss_vlan_mgr_warn("%px: Failed to free VLAN VSI\n", v); - } -#endif - -vlan_instance_free: - nss_vlan_mgr_instance_free(v); - return NOTIFY_DONE; } /* @@ -1355,8 +1360,10 @@ return_with_error: int nss_vlan_mgr_join_bridge(struct net_device *dev, uint32_t bridge_vsi) { struct nss_vlan_pvt *v = nss_vlan_mgr_instance_find_and_ref(dev); +#ifdef NSS_VLAN_MGR_PPE_SUPPORT struct net_device *real_dev; int ret; +#endif if (!v) return 0; @@ -1416,8 +1423,10 @@ EXPORT_SYMBOL(nss_vlan_mgr_join_bridge); int nss_vlan_mgr_leave_bridge(struct net_device *dev, uint32_t bridge_vsi) { struct nss_vlan_pvt *v = nss_vlan_mgr_instance_find_and_ref(dev); +#ifdef NSS_VLAN_MGR_PPE_SUPPORT struct net_device *real_dev; int ret; +#endif if (!v) return 0; --- a/vxlanmgr/nss_vxlanmgr.c +++ b/vxlanmgr/nss_vxlanmgr.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -22,18 +22,15 @@ #include #include #include -#include #include #include #include "nss_vxlanmgr.h" -#include "nss_vxlanmgr_priv.h" #include "nss_vxlanmgr_tun_stats.h" /* * VxLAN context */ struct nss_vxlanmgr_ctx vxlan_ctx; -static struct nss_vxlanmgr_get_ipsec_if_num __rcu ipsecmgr_cb; /* * nss_vxlanmgr_netdev_event() @@ -77,77 +74,6 @@ static struct notifier_block nss_vxlanmg }; /* - * nss_vxlanmgr_bind_ipsec_by_ip() - * Bind VxLAN tunnel with IPsec based on IP Address - */ -int32_t nss_vxlanmgr_bind_ipsec_by_ip(union vxlan_addr *src_ip, union vxlan_addr *dest_ip) -{ - int32_t ipsec_if_num; - nss_vxlanmgr_get_ipsec_if_num_by_ip_callback_t ipsec_cb; - struct nss_ctx_instance *nss_ctx = nss_vxlan_get_ctx(); - - /* - * Check if the VxLAN interface is applied over an IPsec interface by querying the IPsec. - */ - rcu_read_lock(); - ipsec_cb = rcu_dereference(ipsecmgr_cb.get_ifnum_by_ip); - if (!ipsec_cb) { - rcu_read_unlock(); - nss_vxlanmgr_info("%px: IPsec get_ifnum_by_ip callback is not registered\n", nss_ctx); - return -1; - } - - if (dest_ip->sa.sa_family == AF_INET) { - ipsec_if_num = ipsec_cb(IPVERSION, &src_ip->sin.sin_addr.s_addr, &dest_ip->sin.sin_addr.s_addr); - } else { - ipsec_if_num = ipsec_cb(6, src_ip->sin6.sin6_addr.in6_u.u6_addr32, dest_ip->sin6.sin6_addr.in6_u.u6_addr32); - } - - rcu_read_unlock(); - nss_vxlanmgr_info("%px: VxLAN interface is bound to IPsec interface with if_num(0x%x)\n", nss_ctx, ipsec_if_num); - - return ipsec_if_num; -} - -/* - * nss_vxlanmgr_unregister_ipsecmgr_callback_by_ip - * Unregister callback. - */ -void nss_vxlanmgr_unregister_ipsecmgr_callback_by_ip(void) -{ - rcu_assign_pointer(ipsecmgr_cb.get_ifnum_by_ip, NULL); - synchronize_rcu(); -} -EXPORT_SYMBOL(nss_vxlanmgr_unregister_ipsecmgr_callback_by_ip); - -/* - * nss_vxlanmgr_register_ipsecmgr_callback_by_ip() - * Register IPSecmgr callback. - */ -void nss_vxlanmgr_register_ipsecmgr_callback_by_ip(struct nss_vxlanmgr_get_ipsec_if_num *cb) -{ - nss_vxlanmgr_get_ipsec_if_num_by_ip_callback_t ipsec_get_ifnum_by_ip; - - rcu_read_lock(); - ipsec_get_ifnum_by_ip = rcu_dereference(ipsecmgr_cb.get_ifnum_by_ip); - if (ipsec_get_ifnum_by_ip) { - rcu_read_unlock(); - nss_vxlanmgr_info("%px: IPSecmgr Callback get_ifnum_by_ip is already registered\n", cb); - return; - } - rcu_read_unlock(); - - if (cb->get_ifnum_by_ip == NULL) { - nss_vxlanmgr_warn("%px: IPSecmgr Callback get_ifnum_by_ip is NULL\n", cb); - return; - } - - rcu_assign_pointer(ipsecmgr_cb.get_ifnum_by_ip, cb->get_ifnum_by_ip); - synchronize_rcu(); -} -EXPORT_SYMBOL(nss_vxlanmgr_register_ipsecmgr_callback_by_ip); - -/* * nss_vxlanmgr_exit_module() * Tunnel vxlan module exit function */ @@ -194,12 +120,6 @@ int __init nss_vxlanmgr_init_module(void return -1; } - /* - * Initialize ipsecmgr callback. - */ - rcu_assign_pointer(ipsecmgr_cb.get_ifnum_by_ip, NULL); - synchronize_rcu(); - INIT_LIST_HEAD(&vxlan_ctx.list); vxlan_ctx.nss_ctx = nss_vxlan_get_ctx(); spin_lock_init(&vxlan_ctx.tun_lock); --- /dev/null +++ b/vxlanmgr/nss_vxlanmgr.h @@ -0,0 +1,85 @@ +/* + ************************************************************************** + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + ************************************************************************** + */ + +/* + * nss_vxlanmgr.h + * VxLAN manager header + */ +#ifndef __NSS_VXLANMGR_H +#define __NSS_VXLANMGR_H + +/* + * Compile messages for dynamic enable/disable + */ +#if defined(CONFIG_DYNAMIC_DEBUG) +#define nss_vxlanmgr_warn(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define nss_vxlanmgr_info(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define nss_vxlanmgr_trace(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else /* CONFIG_DYNAMIC_DEBUG */ +/* + * Statically compile messages at different levels + */ +#if (NSS_VXLANMGR_DEBUG_LEVEL < 2) +#define nss_vxlanmgr_warn(s, ...) +#else +#define nss_vxlanmgr_warn(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#if (NSS_VXLANMGR_DEBUG_LEVEL < 3) +#define nss_vxlanmgr_info(s, ...) +#else +#define nss_vxlanmgr_info(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#if (NSS_VXLANMGR_DEBUG_LEVEL < 4) +#define nss_vxlanmgr_trace(s, ...) +#else +#define nss_vxlanmgr_trace(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif +#endif /* CONFIG_DYNAMIC_DEBUG */ + +struct nss_vxlanmgr_ctx { + struct list_head list; /* vxlanmgr context list head */ + struct dentry *dentry; /* debugfs entry for qca-nss-vxlanmgr */ + struct nss_ctx_instance *nss_ctx; /* nss context for vxlan tunnel */ + uint32_t tun_count; /* active vxlan tunnel count */ + spinlock_t tun_lock; /* spinlock */ +}; + +struct nss_vxlanmgr_tun_ctx { + struct list_head head; /* tunnel context list entry */ + struct net_device *dev; /* tunnel netdevice pointer */ + struct dentry *dentry; /* per tunnel debugfs entry */ + struct nss_vxlanmgr_ctx *vxlan_ctx; /* pointer to vxlanmgr context */ + struct nss_vxlanmgr_tun_stats *stats; /* tunnel statistics structure */ + uint32_t inner_ifnum; /* inner node interface number */ + uint32_t outer_ifnum; /* outer node interface number */ + uint32_t vni; /* vnet identifier */ + uint16_t tunnel_flags; /* vxlan tunnel flags */ + uint16_t flow_label; /* flowlabel */ + uint16_t src_port_min; /* minimum source port */ + uint16_t src_port_max; /* maximum source port*/ + uint16_t dest_port; /* destination port */ + uint8_t tos; /* tos value */ + uint8_t ttl; /* time to live */ +}; + +extern int nss_vxlanmgr_tunnel_create(struct net_device *dev); +extern int nss_vxlanmgr_tunnel_destroy(struct net_device *dev); +extern int nss_vxlanmgr_tunnel_config(struct net_device *dev); +extern int nss_vxlanmgr_tunnel_deconfig(struct net_device *dev); + +#endif /* __NSS_VXLANMGR_H */ --- a/vxlanmgr/nss_vxlanmgr_tun_stats.c +++ b/vxlanmgr/nss_vxlanmgr_tun_stats.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -18,7 +18,7 @@ #include #include #include -#include "nss_vxlanmgr_priv.h" +#include "nss_vxlanmgr.h" #include "nss_vxlanmgr_tun_stats.h" /* @@ -47,8 +47,6 @@ static int8_t *nss_vxlanmgr_tun_stats_st "Except VNI Look-up failed", "Dropped packet malformed", "Dropped next node queue is full", - "Except Inner hash calculation failed", - "Decap IPSec source interface invalid" }; /* @@ -90,7 +88,7 @@ static int nss_vxlanmgr_tun_stats_show(s seq_printf(m, "\t\tflow_label = %u\n", tun_ctx->flow_label); seq_printf(m, "\t\tsrc_port_min = %u\n", tun_ctx->src_port_min); seq_printf(m, "\t\tsrc_port_max = %u\n", tun_ctx->src_port_max); - seq_printf(m, "\t\tdest_port = %u\n", tun_ctx->dest_port); + seq_printf(m, "\t\tdest_port = %u\n", ntohs(tun_ctx->dest_port)); seq_printf(m, "\t\ttos = %u\n", tun_ctx->tos); seq_printf(m, "\t\tttl = %u\n", tun_ctx->ttl); @@ -167,16 +165,11 @@ void nss_vxlanmgr_tun_stats_update(uint6 stats_msg->dropped_malformed; stats[NSS_VXLANMGR_TUN_STATS_TYPE_DROP_NEXT_NODE_QUEUE_FULL] += stats_msg->dropped_next_node_queue_full; - stats[NSS_VXLANMGR_TUN_STATS_TYPE_EXCEPT_INNER_HASH] += - stats_msg->except_inner_hash; - stats[NSS_VXLANMGR_TUN_STATS_TYPE_DECAP_IPSEC_SRC_INVALID] += - stats_msg->decap_ipsec_src_err; } /* * nss_vxlanmgr_tun_macdb_stats_sync() * Sync function for vxlan fdb entries - * Note: Reference on the netdevice is expected to be held by the caller at the time this function is called. */ void nss_vxlanmgr_tun_macdb_stats_sync(struct nss_vxlanmgr_tun_ctx *tun_ctx, struct nss_vxlan_msg *nvm) { @@ -187,8 +180,11 @@ void nss_vxlanmgr_tun_macdb_stats_sync(s db_stats = &nvm->msg.db_stats; nentries = db_stats->cnt; + dev_hold(tun_ctx->dev); + if (nentries > NSS_VXLAN_MACDB_ENTRIES_PER_MSG) { nss_vxlanmgr_warn("%px: No more than 20 entries allowed per message.\n", tun_ctx->dev); + dev_put(tun_ctx->dev); return; } @@ -204,6 +200,7 @@ void nss_vxlanmgr_tun_macdb_stats_sync(s } } } + dev_put(tun_ctx->dev); } /* --- a/vxlanmgr/nss_vxlanmgr_tun_stats.h +++ b/vxlanmgr/nss_vxlanmgr_tun_stats.h @@ -1,6 +1,6 @@ /* ****************************************************************************** - * Copyright (c) 2019, 2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2019, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -37,8 +37,6 @@ enum nss_vxlanmgr_tun_stats_type { NSS_VXLANMGR_TUN_STATS_TYPE_EXCEPT_VNI_LOOKUP_FAILED, NSS_VXLANMGR_TUN_STATS_TYPE_DROP_MALFORMED, NSS_VXLANMGR_TUN_STATS_TYPE_DROP_NEXT_NODE_QUEUE_FULL, - NSS_VXLANMGR_TUN_STATS_TYPE_EXCEPT_INNER_HASH, - NSS_VXLANMGR_TUN_STATS_TYPE_DECAP_IPSEC_SRC_INVALID, NSS_VXLANMGR_TUN_STATS_TYPE_MAX, }; --- a/vxlanmgr/nss_vxlanmgr_tunnel.c +++ b/vxlanmgr/nss_vxlanmgr_tunnel.c @@ -1,6 +1,6 @@ /* ************************************************************************** - * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. @@ -27,7 +27,7 @@ #include #include #include -#include "nss_vxlanmgr_priv.h" +#include "nss_vxlanmgr.h" #include "nss_vxlanmgr_tun_stats.h" /* @@ -91,23 +91,18 @@ static uint16_t nss_vxlanmgr_tunnel_flag uint16_t flags = 0; uint32_t priv_flags = priv->flags; - if (priv_flags & VXLAN_F_RSC) - return flags; if (priv_flags & VXLAN_F_GBP) flags |= NSS_VXLAN_RULE_FLAG_GBP_ENABLED; - - if (priv_flags & VXLAN_F_IPV6) { + if (priv_flags & VXLAN_F_IPV6) flags |= NSS_VXLAN_RULE_FLAG_IPV6; - if (!(priv_flags & VXLAN_F_UDP_ZERO_CSUM6_TX)) - flags |= NSS_VXLAN_RULE_FLAG_ENCAP_L4_CSUM_REQUIRED; - } else { + else if (!(priv_flags & VXLAN_F_IPV6)) flags |= NSS_VXLAN_RULE_FLAG_IPV4; - if (priv_flags & VXLAN_F_UDP_CSUM) - flags |= NSS_VXLAN_RULE_FLAG_ENCAP_L4_CSUM_REQUIRED; - } - if (priv->cfg.tos == 1) flags |= NSS_VXLAN_RULE_FLAG_INHERIT_TOS; + if (priv_flags & VXLAN_F_UDP_CSUM) + flags |= NSS_VXLAN_RULE_FLAG_ENCAP_L4_CSUM_REQUIRED; + else if (!(priv_flags & VXLAN_F_UDP_ZERO_CSUM6_TX)) + flags |= NSS_VXLAN_RULE_FLAG_ENCAP_L4_CSUM_REQUIRED; return (flags | NSS_VXLAN_RULE_FLAG_UDP); } @@ -118,25 +113,18 @@ static uint16_t nss_vxlanmgr_tunnel_flag struct vxlan_config *cfg = &priv->cfg; uint32_t priv_flags = cfg->flags; - if (priv_flags & VXLAN_F_RSC) - return flags; - if (priv_flags & VXLAN_F_GPE) - return flags; if (priv_flags & VXLAN_F_GBP) flags |= NSS_VXLAN_RULE_FLAG_GBP_ENABLED; - - if (priv_flags & VXLAN_F_IPV6) { + if (priv_flags & VXLAN_F_IPV6) flags |= NSS_VXLAN_RULE_FLAG_IPV6; - if (!(priv_flags & VXLAN_F_UDP_ZERO_CSUM6_TX)) - flags |= NSS_VXLAN_RULE_FLAG_ENCAP_L4_CSUM_REQUIRED; - } else { + else if (!(priv_flags & VXLAN_F_IPV6)) flags |= NSS_VXLAN_RULE_FLAG_IPV4; - if (!(priv_flags & VXLAN_F_UDP_ZERO_CSUM_TX)) - flags |= NSS_VXLAN_RULE_FLAG_ENCAP_L4_CSUM_REQUIRED; - } - if (cfg->tos == 1) flags |= NSS_VXLAN_RULE_FLAG_INHERIT_TOS; + if (priv_flags & VXLAN_F_UDP_ZERO_CSUM_TX) + flags |= NSS_VXLAN_RULE_FLAG_ENCAP_L4_CSUM_REQUIRED; + else if (!(priv_flags & VXLAN_F_UDP_ZERO_CSUM6_TX)) + flags |= NSS_VXLAN_RULE_FLAG_ENCAP_L4_CSUM_REQUIRED; return (flags | NSS_VXLAN_RULE_FLAG_UDP); } @@ -323,7 +311,6 @@ static nss_tx_status_t nss_vxlanmgr_tunn union vxlan_addr *remote_ip, *src_ip; uint32_t i, inner_ifnum; uint32_t new_src_ip[4] = {0}; - int32_t ipsec_if_num; nss_tx_status_t status = NSS_TX_FAILURE; dev = vfe->dev; @@ -380,17 +367,6 @@ static nss_tx_status_t nss_vxlanmgr_tunn } /* - * Check if this is a VxLAN over IPsec use case. If so, we need to bind the IPsec interface to the VxLAN. - * When the IPsec interface is deleted in NSS, user is expected to bring the vxlan interface down as well, thereby flushing the MAC entries in NSS. - */ - ipsec_if_num = nss_vxlanmgr_bind_ipsec_by_ip(src_ip, remote_ip); - if (ipsec_if_num > 0) { - mac_add_msg->ipsec_if_num = (uint32_t)ipsec_if_num; - mac_add_msg->flags = mac_add_msg->flags | NSS_VXLAN_MAC_ENABLE_IPSEC_BIND; - nss_vxlanmgr_trace("%px: VxLAN interface is bound to IPsec interface with if_num(0x%x)\n", dev, ipsec_if_num); - } - - /* * Send MAC add message asynchronously as it is called by chain * notifier in atomic context from the vxlan driver. */ @@ -460,8 +436,7 @@ static struct notifier_block nss_vxlanmg /* * nss_vxlanmgr_tunnel_inner_stats() - * Update vxlan netdev stats with inner node stats. - * Note: Reference on the netdevice is expected to be held by the caller at the time this function is called. + * Update vxlan netdev stats with inner node stats */ static void nss_vxlanmgr_tunnel_inner_stats(struct nss_vxlanmgr_tun_ctx *tun_ctx, struct nss_vxlan_msg *nvm) { @@ -475,6 +450,7 @@ static void nss_vxlanmgr_tunnel_inner_st stats = &nvm->msg.stats; dev = tun_ctx->dev; + dev_hold(dev); netdev_stats = (struct net_device_stats *)&dev->stats; /* @@ -493,6 +469,7 @@ static void nss_vxlanmgr_tunnel_inner_st tstats->tx_bytes += stats->node_stats.tx_bytes; u64_stats_update_end(&tstats->syncp); netdev_stats->tx_dropped += dropped; + dev_put(dev); } /* @@ -537,7 +514,7 @@ static void nss_vxlanmgr_tunnel_outer_st * nss_vxlanmgr_tunnel_fdb_update() * Update vxlan fdb entries */ -static void nss_vxlanmgr_tunnel_fdb_update(struct net_device *dev, uint32_t vni, struct nss_vxlan_msg *nvm) +static void nss_vxlanmgr_tunnel_fdb_update(struct nss_vxlanmgr_tun_ctx *tun_ctx, struct nss_vxlan_msg *nvm) { uint8_t *mac; uint16_t i, nentries; @@ -546,10 +523,13 @@ static void nss_vxlanmgr_tunnel_fdb_upda db_stats = &nvm->msg.db_stats; nentries = db_stats->cnt; - priv = netdev_priv(dev); + priv = netdev_priv(tun_ctx->dev); + + dev_hold(tun_ctx->dev); if (nentries > NSS_VXLAN_MACDB_ENTRIES_PER_MSG) { - nss_vxlanmgr_warn("%px: No more than 20 entries allowed per message.\n", dev); + nss_vxlanmgr_warn("%px: No more than 20 entries allowed per message.\n", tun_ctx->dev); + dev_put(tun_ctx->dev); return; } @@ -559,10 +539,11 @@ static void nss_vxlanmgr_tunnel_fdb_upda #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 5, 7)) vxlan_fdb_update_mac(priv, mac); #else - vxlan_fdb_update_mac(priv, mac, vni); + vxlan_fdb_update_mac(priv, mac, tun_ctx->vni); #endif } } + dev_put(tun_ctx->dev); } /* @@ -574,29 +555,20 @@ static void nss_vxlanmgr_tunnel_inner_no struct net_device *dev = (struct net_device *)app_data; struct nss_vxlanmgr_tun_ctx *tun_ctx; struct nss_vxlan_msg *nvm; - uint32_t vni; if (!ncm) { nss_vxlanmgr_info("%px: NULL msg received.\n", dev); return; } - if (!dev) { - nss_vxlanmgr_info("%px: NULL device received.\n", dev); - return; - } - spin_lock_bh(&vxlan_ctx.tun_lock); - dev_hold(dev); tun_ctx = nss_vxlanmgr_tunnel_ctx_dev_get(dev); if (!tun_ctx) { spin_unlock_bh(&vxlan_ctx.tun_lock); nss_vxlanmgr_warn("%px: Invalid tunnel context\n", dev); - dev_put(dev); return; } - vni = tun_ctx->vni; nvm = (struct nss_vxlan_msg *)ncm; switch (nvm->cm.type) { case NSS_VXLAN_MSG_TYPE_STATS_SYNC: @@ -604,24 +576,14 @@ static void nss_vxlanmgr_tunnel_inner_no nss_vxlanmgr_tun_stats_sync(tun_ctx, nvm); break; case NSS_VXLAN_MSG_TYPE_MACDB_STATS: + nss_vxlanmgr_tunnel_fdb_update(tun_ctx, nvm); nss_vxlanmgr_tun_macdb_stats_sync(tun_ctx, nvm); - - /* - * Release the lock before updating the Linux FDB entry. - * This will ensure there is no deadlock when a potential - * MAC add event occurs at same time, which needs to hold - * the kernel's hash lock followed by the tunnel ctx lock. - */ - spin_unlock_bh(&vxlan_ctx.tun_lock); - - nss_vxlanmgr_tunnel_fdb_update(dev, vni, nvm); - dev_put(dev); - return; + break; default: + spin_unlock_bh(&vxlan_ctx.tun_lock); nss_vxlanmgr_info("%px: Unknown Event from NSS", dev); + return; } - - dev_put(dev); spin_unlock_bh(&vxlan_ctx.tun_lock); } @@ -867,7 +829,7 @@ done: */ int nss_vxlanmgr_tunnel_destroy(struct net_device *dev) { - uint32_t inner_ifnum, outer_ifnum, tun_count; + uint32_t inner_ifnum, outer_ifnum; struct nss_vxlanmgr_tun_ctx *tun_ctx; struct nss_vxlan_msg vxlanmsg; nss_tx_status_t ret; @@ -904,21 +866,16 @@ int nss_vxlanmgr_tunnel_destroy(struct n nss_vxlanmgr_tun_stats_deinit(tun_ctx); nss_vxlanmgr_tun_stats_dentry_remove(tun_ctx); - dev_put(tun_ctx->dev); kfree(tun_ctx); - /* - * Unregister fdb notifier chain if - * all vxlan tunnels are destroyed. - */ - spin_lock_bh(&vxlan_ctx.tun_lock); - tun_count = vxlan_ctx.tun_count; - spin_unlock_bh(&vxlan_ctx.tun_lock); - if (!tun_count) { + if (!vxlan_ctx.tun_count) { + /* + * Unregister fdb notifier chain if + * all vxlan tunnels are destroyed. + */ vxlan_fdb_unregister_notify(&nss_vxlanmgr_tunnel_fdb_notifier); } - - nss_vxlanmgr_info("%px: VxLAN interface count is #%d\n", dev, tun_count); + nss_vxlanmgr_info("%px: VxLAN interface count is #%d\n", dev, vxlan_ctx.tun_count); memset(&vxlanmsg, 0, sizeof(struct nss_vxlan_msg)); ret = nss_vxlanmgr_tunnel_tx_msg_sync(vxlan_ctx.nss_ctx, @@ -972,7 +929,6 @@ int nss_vxlanmgr_tunnel_create(struct ne struct nss_vxlan_rule_msg *vxlan_cfg; struct nss_ctx_instance *nss_ctx; uint32_t inner_ifnum, outer_ifnum; - uint16_t parse_flags; nss_tx_status_t ret; spin_lock_bh(&vxlan_ctx.tun_lock); @@ -983,20 +939,7 @@ int nss_vxlanmgr_tunnel_create(struct ne } spin_unlock_bh(&vxlan_ctx.tun_lock); - /* - * The reference to the dev will be released in nss_vxlanmgr_tunnel_destroy() - */ dev_hold(dev); - priv = netdev_priv(dev); - parse_flags = nss_vxlanmgr_tunnel_flags_parse(priv); - - /* - * Check if the tunnel is supported. - */ - if (!parse_flags) { - nss_vxlanmgr_warn("%px: Tunnel offload not supported\n", dev); - goto ctx_alloc_fail; - } tun_ctx = kzalloc(sizeof(struct nss_vxlanmgr_tun_ctx), GFP_ATOMIC); if (!tun_ctx) { @@ -1045,11 +988,12 @@ int nss_vxlanmgr_tunnel_create(struct ne memset(&vxlanmsg, 0, sizeof(struct nss_vxlan_msg)); vxlan_cfg = &vxlanmsg.msg.vxlan_create; + priv = netdev_priv(dev); vxlan_cfg->vni = vxlan_get_vni(priv); - vxlan_cfg->tunnel_flags = parse_flags; + vxlan_cfg->tunnel_flags = nss_vxlanmgr_tunnel_flags_parse(priv); vxlan_cfg->src_port_min = priv->cfg.port_min; vxlan_cfg->src_port_max = priv->cfg.port_max; - vxlan_cfg->dest_port = ntohs(priv->cfg.dst_port); + vxlan_cfg->dest_port = priv->cfg.dst_port; vxlan_cfg->tos = priv->cfg.tos; vxlan_cfg->ttl = (priv->cfg.ttl ? priv->cfg.ttl : IPDEFTTL); @@ -1115,6 +1059,7 @@ int nss_vxlanmgr_tunnel_create(struct ne spin_unlock_bh(&vxlan_ctx.tun_lock); nss_vxlanmgr_info("%px: VxLAN interface count is #%d\n", dev, vxlan_ctx.tun_count); + dev_put(dev); return NOTIFY_DONE; config_fail: --- a/wifi_meshmgr/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -ccflags-y += -I$(obj)/../exports -I$(obj)/.. -I$(obj)/nss_hal/include -ccflags-y += -DNSS_CLIENT_BUILD_ID="$(BUILD_ID)" -ccflags-y += -DNSS_WIFI_MESHMGR_DEBUG_LEVEL=4 -ccflags-y += -Wall -Werror - -obj-m += qca-nss-wifi-meshmgr.o -qca-nss-wifi-meshmgr-objs := nss_wifi_meshmgr.o --- a/wifi_meshmgr/nss_wifi_mesh_priv.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - ************************************************************************** - * Copyright (c) 2021, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ************************************************************************** - */ - -/* - * nss_wifi_mesh_priv.h - * Mesh manager header - */ -#ifndef __NSS_WIFI_MESH_PRIV_H_ -#define __NSS_WIFI_MESH_PRIV_H_ - -#define NSS_WIFI_MESH_MAX 16 - -/* - * Compile messages for dynamic enable/disable - */ -#if defined(CONFIG_DYNAMIC_DEBUG) -#define nss_wifi_meshmgr_warn(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define nss_wifi_meshmgr_info(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define nss_wifi_meshmgr_trace(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#else /* CONFIG_DYNAMIC_DEBUG */ -/* - * Statically compile messages at different levels - */ -#if (NSS_WIFI_MESHMGR_DEBUG_LEVEL < 2) -#define nss_wifi_meshmgr_warn(s, ...) -#else -#define nss_wifi_meshmgr_warn(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif - -#if (NSS_WIFI_MESHMGR_DEBUG_LEVEL < 3) -#define nss_wifi_meshmgr_info(s, ...) -#else -#define nss_wifi_meshmgr_info(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif - -#if (NSS_WIFI_MESHMGR_DEBUG_LEVEL < 4) -#define nss_wifi_meshmgr_trace(s, ...) -#else -#define nss_wifi_meshmgr_trace(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif -#endif /* CONFIG_DYNAMIC_DEBUG */ - -/* - * nss_wifi_meshmgr_mesh_ctx - * Mesh context per interface. - */ -struct nss_wifi_meshmgr_mesh_ctx { - struct net_device *dev; /* Netdevice pointer */ - atomic_t ref; /* Atomic reference count */ - int32_t encap_ifnum; /* Encap interface number */ - int32_t decap_ifnum; /* Decap interface number */ - struct semaphore sem; /* Semaphore for message synchronization */ - struct completion complete; /* Per context complete */ - nss_tx_status_t response; /* Response type */ -}; - -/* - * nss_wifi_meshmgr_ctx - * Global mesh context. - */ -struct nss_wifi_meshmgr_ctx { - struct nss_ctx_instance *nss_ctx; /* Nss context for mesh */ - uint32_t mesh_count; /* Active mesh count */ - spinlock_t ref_lock; /* Spinlock */ - struct nss_wifi_meshmgr_mesh_ctx *mesh_ctx[NSS_WIFI_MESH_MAX]; - /* Mesh handle table */ -}; -#endif /* __NSS_WIFI_MESH_PRIV_H_ */ --- a/wifi_meshmgr/nss_wifi_meshmgr.c +++ /dev/null @@ -1,2005 +0,0 @@ -/* - ************************************************************************** - * Copyright (c) 2021, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ************************************************************************** - */ - -/* - * nss_wifi_meshmgr.c - * NSS to HLOS WiFi-Mesh manager - */ - -#include -#include -#include -#include -#include -#include "nss_wifi_mesh_priv.h" - -/* - * WiFi-Mesh context - */ -static struct nss_wifi_meshmgr_ctx wmgr_ctx; - -/* - * nss_wifi_meshmgr_verify_if_num() - * Verify interface number. - */ -static bool nss_wifi_meshmgr_verify_if_num(int32_t if_num, enum nss_dynamic_interface_type di_type) -{ - return (nss_is_dynamic_interface(if_num) && - (nss_dynamic_interface_get_type(wmgr_ctx.nss_ctx, if_num) == di_type)); -} - -/* - * nss_wifi_meshmgr_tx_msg() - * WiFi-Mesh message send API - */ -static nss_wifi_meshmgr_status_t nss_wifi_meshmgr_tx_msg(struct nss_wifi_mesh_msg *msg) -{ - return nss_wifi_mesh_tx_msg(wmgr_ctx.nss_ctx, msg); -} - -/* - * nss_wifi_meshmgr_ctx_insert() - * Insert the mesh context into global table - */ -static int32_t nss_wifi_meshmgr_ctx_insert(struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx) -{ - int32_t i, idx = -1; - struct net_device *dev; - - assert_spin_locked(&wmgr_ctx.ref_lock); - - /* - * Check if the context already exist for the same netdev. - */ - for (i = 0; i < NSS_WIFI_MESH_MAX; i++) { - if (!wmgr_ctx.mesh_ctx[i]) { - idx = i; - continue; - } - - dev = (wmgr_ctx.mesh_ctx[i])->dev; - if (dev == wmesh_ctx->dev) { - nss_wifi_meshmgr_warn("%px: The mesh context already exist for dev:%s", - &wmgr_ctx, wmesh_ctx->dev->name); - return -1; - } - } - - if (idx == -1) { - return idx; - } - - wmgr_ctx.mesh_ctx[idx] = wmesh_ctx; - return idx; -} - -/* - * nss_wifi_meshmgr_ctx_remove() - * Remove the mesh context from global table - */ -static void nss_wifi_meshmgr_ctx_remove(struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx) -{ - int32_t i; - - assert_spin_locked(&wmgr_ctx.ref_lock); - - for (i = 0; i < NSS_WIFI_MESH_MAX; i++) { - if (wmgr_ctx.mesh_ctx[i] != wmesh_ctx) { - continue; - } - - wmgr_ctx.mesh_ctx[i] = NULL; - return; - } -} - -/* - * nss_wifi_meshmgr_cleanup() - * Clean up the mesh context. - */ -static void nss_wifi_meshmgr_cleanup(struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx) -{ - int32_t encap_ifnum, decap_ifnum; - nss_wifi_meshmgr_status_t nss_status; - - nss_wifi_meshmgr_trace("%px: Mesh handle cleanup called for: %s\n", &wmgr_ctx, wmesh_ctx->dev->name); - - encap_ifnum = wmesh_ctx->encap_ifnum; - decap_ifnum = wmesh_ctx->decap_ifnum; - - /* - * Unregister and dealloc decap DI. - */ - nss_unregister_wifi_mesh_if(decap_ifnum); - nss_status = nss_dynamic_interface_dealloc_node(decap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_OUTER); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Failed to dealloc decap: %d\n", &wmgr_ctx, nss_status); - } - - /* - * Unregister and dealloc encap DI. - */ - nss_unregister_wifi_mesh_if(encap_ifnum); - nss_status = nss_dynamic_interface_dealloc_node(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Failed to dealloc encap: %d\n", &wmgr_ctx, nss_status); - } - - dev_put(wmesh_ctx->dev); - kfree(wmesh_ctx); -} - -/* - * nss_wifi_meshmgr_ref_dec() - * Find and decrement the reference counter. - */ -static void nss_wifi_meshmgr_ref_dec(struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx) -{ - if (atomic_dec_and_test(&wmesh_ctx->ref)) { - nss_wifi_meshmgr_cleanup(wmesh_ctx); - } -} - -/* - * nss_wifi_meshmgr_find_and_ref_inc() - * Find and inreae the reference counter. - */ -static struct nss_wifi_meshmgr_mesh_ctx *nss_wifi_meshmgr_find_and_ref_inc(nss_wifi_mesh_handle_t mesh_handle) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - - if ((mesh_handle < 0) || (mesh_handle >= NSS_WIFI_MESH_MAX)) { - nss_wifi_meshmgr_warn("%px: Invalid mesh handle: %d\n", &wmgr_ctx, mesh_handle); - return NULL; - } - - spin_lock_bh(&wmgr_ctx.ref_lock); - wmesh_ctx = wmgr_ctx.mesh_ctx[mesh_handle]; - if (wmesh_ctx && atomic_inc_and_test(&wmesh_ctx->ref)) { - BUG_ON(1); - } - spin_unlock_bh(&wmgr_ctx.ref_lock); - return wmesh_ctx; -} - -/* - * nss_wifi_meshmgr_remap_error() - * Remap the error code. - */ -static nss_wifi_meshmgr_status_t nss_wifi_meshmgr_remap_error(enum nss_wifi_mesh_error_types error) -{ - switch (error) { - case NSS_WIFI_MESH_ERROR_UNKNOWN_MSG: - return NSS_WIFI_MESHMGR_FAILURE_UNKNOWN_MSG; - case NSS_WIFI_MESH_ERROR_TTL_CONFIG: - return NSS_WIFI_MESHMGR_FAILURE_TTL_CONFIG; - case NSS_WIFI_MESH_ERROR_REFRESH_TIME_CONFIG: - return NSS_WIFI_MESHMGR_FAILURE_REFRESH_TIME_CONFIG; - case NSS_WIFI_MESH_ERROR_MPP_LEARNING_MODE_CONFIG: - return NSS_WIFI_MESHMGR_FAILURE_MPP_LEARNING_MODE_CONFIG; - case NSS_WIFI_MESH_ERROR_PATH_ADD_MAX_RADIO_CNT: - return NSS_WIFI_MESHMGR_FAILURE_PATH_ADD_MAX_RADIO_CNT; - case NSS_WIFI_MESH_ERROR_PATH_ADD_INVALID_INTERFACE_NUM: - return NSS_WIFI_MESHMGR_FAILURE_PATH_ADD_INVALID_INTERFACE_NUM; - case NSS_WIFI_MESH_ERROR_PATH_ADD_INTERFACE_NUM_NOT_FOUND: - return NSS_WIFI_MESHMGR_FAILURE_PATH_ADD_INTERFACE_NUM_NOT_FOUND; - case NSS_WIFI_MESH_ERROR_PATH_TABLE_FULL: - return NSS_WIFI_MESHMGR_FAILURE_PATH_TABLE_FULL; - case NSS_WIFI_MESH_ERROR_PATH_ALLOC_FAIL: - return NSS_WIFI_MESHMGR_FAILURE_PATH_ALLOC_FAIL; - case NSS_WIFI_MESH_ERROR_PATH_INSERT_FAIL: - return NSS_WIFI_MESHMGR_FAILURE_PATH_INSERT_FAIL; - case NSS_WIFI_MESH_ERROR_PATH_NOT_FOUND: - return NSS_WIFI_MESHMGR_FAILURE_PATH_NOT_FOUND; - case NSS_WIFI_MESH_ERROR_PATH_UNHASHED: - return NSS_WIFI_MESHMGR_FAILURE_PATH_UNHASHED; - case NSS_WIFI_MESH_ERROR_PATH_DELETE_FAIL: - return NSS_WIFI_MESHMGR_FAILURE_PATH_DELETE_FAIL; - case NSS_WIFI_MESH_ERROR_PROXY_PATH_NOT_FOUND: - return NSS_WIFI_MESHMGR_FAILURE_PROXY_PATH_NOT_FOUND; - case NSS_WIFI_MESH_ERROR_PROXY_PATH_UNHASHED: - return NSS_WIFI_MESHMGR_FAILURE_PROXY_PATH_UNHASHED; - case NSS_WIFI_MESH_ERROR_PROXY_PATH_DELETE_FAIL: - return NSS_WIFI_MESHMGR_FAILURE_PROXY_PATH_DELETE_FAIL; - case NSS_WIFI_MESH_ERROR_PROXY_PATH_EXISTS: - return NSS_WIFI_MESHMGR_FAILURE_PROXY_PATH_EXISTS; - case NSS_WIFI_MESH_ERROR_PROXY_PATH_ALLOC_FAIL: - return NSS_WIFI_MESHMGR_FAILURE_PROXY_PATH_ALLOC_FAIL; - case NSS_WIFI_MESH_ERROR_PROXY_PATH_INSERT_FAIL: - return NSS_WIFI_MESHMGR_FAILURE_PROXY_PATH_INSERT_FAIL; - case NSS_WIFI_MESH_ERROR_PROXY_PATH_TABLE_FULL: - return NSS_WIFI_MESHMGR_FAILURE_PROXY_PATH_TABLE_FULL; - case NSS_WIFI_MESH_ERROR_PB_ALLOC_FAIL: - return NSS_WIFI_MESHMGR_FAILURE_PB_ALLOC_FAIL; - case NSS_WIFI_MESH_ERROR_ENQUEUE_TO_HOST_FAIL: - return NSS_WIFI_MESHMGR_FAILURE_ENQUEUE_TO_HOST_FAIL; - case NSS_WIFI_MESH_ERROR_ENABLE_INTERFACE_FAIL: - return NSS_WIFI_MESHMGR_FAILURE_ENABLE_INTERFACE_FAIL; - case NSS_WIFI_MESH_ERROR_DISABLE_INTERFACE_FAIL: - return NSS_WIFI_MESHMGR_FAILURE_DISABLE_INTERFACE_FAIL; - case NSS_WIFI_MESH_ERROR_INVALID_EXCEPTION_NUM: - return NSS_WIFI_MESHMGR_FAILURE_INVALID_EXCEPTION_NUM; - case NSS_WIFI_MESH_ERROR_ONESHOT_ALREADY_ATTACHED: - return NSS_WIFI_MESHMGR_FAILURE_ONESHOT_ALREADY_ATTACHED; - case NSS_WIFI_MESH_ERROR_DUMMY_PATH_ADD_FAILED: - return NSS_WIFI_MESHMGR_FAILURE_DUMMY_PATH_ADD; - case NSS_WIFI_MESH_ERROR_DUMMY_PROXY_PATH_ADD_FAILED: - return NSS_WIFI_MESHMGR_FAILURE_DUMMY_PROXY_PATH_ADD; - default: - return NSS_WIFI_MESHMGR_FAILURE; - }; -} - -/* - * nss_wifi_meshmgr_tx_msg_cb() - * Callback to handle the completion of NSS->HLOS messages. - */ -static void nss_wifi_meshmgr_tx_msg_cb(void *app_data, struct nss_cmn_msg *ncm) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx = (struct nss_wifi_meshmgr_mesh_ctx *)app_data; - uint32_t error_code = ncm->error; - - /* - * FIXME: The wmesh_ctx can be invalid if the memory goes away with the caller being timedout. - */ - wmesh_ctx->response = NSS_WIFI_MESHMGR_SUCCESS; - if (ncm->response != NSS_CMN_RESPONSE_ACK) { - nss_wifi_meshmgr_warn("%px: WiFi-Mesh error response %d error_code: %u\n", &wmgr_ctx, ncm->response, error_code); - wmesh_ctx->response = nss_wifi_meshmgr_remap_error(error_code); - } - - complete(&wmesh_ctx->complete); -} - - /* - * nss_wifi_meshmgr_tx_msg_sync() - * Transmit a WiFi mesh message to NSS firmware synchronously. - */ -static nss_wifi_meshmgr_status_t nss_wifi_meshmgr_tx_msg_sync(struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx, struct nss_wifi_mesh_msg *wmesh_msg) -{ - nss_wifi_meshmgr_status_t status; - int ret; - - down(&wmesh_ctx->sem); - status = nss_wifi_meshmgr_tx_msg(wmesh_msg); - if (status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: WiFi mesh tx sync msg failed: %d\n", &wmgr_ctx, status); - up(&wmesh_ctx->sem); - return status; - } - - /* - * Wait for the acknowledgement. - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - return status; -} - -/* - * nss_wifi_meshmgr_tx_buf() - * Send packets to mesh I/F - */ -nss_wifi_meshmgr_status_t nss_wifi_meshmgr_tx_buf(nss_wifi_mesh_handle_t mesh_handle, struct sk_buff *os_buf) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - int32_t encap_ifnum; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - nss_status = nss_wifi_mesh_tx_buf(wmgr_ctx.nss_ctx, os_buf, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_tx_buf); - -/* - * nss_wifi_meshmgr_if_down() - * Make the NSS interface down synchronously. - */ -nss_wifi_meshmgr_status_t nss_wifi_meshmgr_if_down(nss_wifi_mesh_handle_t mesh_handle) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - nss_wifi_meshmgr_status_t nss_status; - int32_t encap_ifnum, decap_ifnum; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - decap_ifnum = wmesh_ctx->decap_ifnum; - - /* - * Verify the I/F encap and decap number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER) || - nss_wifi_meshmgr_verify_if_num(decap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_OUTER))) { - nss_wifi_meshmgr_warn("%px: Interface verification failed\n", &wmgr_ctx); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the encap I/F down message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_IF_CLOSE, - sizeof(struct nss_if_close), nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - - /* - * Send the I/F down message to the encap I/F. - */ - nss_status = nss_wifi_meshmgr_tx_msg_sync(wmesh_ctx, &wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh link encap I/F down failed: %d.\n", &wmgr_ctx, nss_status); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Initialize the decap I/F down message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nss_wifi_mesh_msg_init(&wmesh_msg, decap_ifnum, NSS_IF_CLOSE, - sizeof(struct nss_if_close), nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - - /* - * Send the I/F down message to the decap I/F. - */ - nss_status = nss_wifi_meshmgr_tx_msg_sync(wmesh_ctx, &wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh link decap I/F down failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_if_down); - -/* - * nss_wifi_meshmgr_if_up() - * Make the NSS interface up synchronously. - */ -nss_wifi_meshmgr_status_t nss_wifi_meshmgr_if_up(nss_wifi_mesh_handle_t mesh_handle) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - nss_wifi_meshmgr_status_t nss_status; - int32_t encap_ifnum, decap_ifnum; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - decap_ifnum = wmesh_ctx->decap_ifnum; - - /* - * Verify the I/F encap and decap number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER) || - nss_wifi_meshmgr_verify_if_num(decap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_OUTER))) { - nss_wifi_meshmgr_warn("%px: Interface verification failed\n", &wmgr_ctx); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the encap I/F up message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_IF_OPEN, - sizeof(struct nss_if_open), nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - - /* - * Send the I/F up message to the encap I/F. - */ - nss_status = nss_wifi_meshmgr_tx_msg_sync(wmesh_ctx, &wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh link encap I/F up failed: %d.\n", &wmgr_ctx, nss_status); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Initialize the I/F decap up message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nss_wifi_mesh_msg_init(&wmesh_msg, decap_ifnum, NSS_IF_OPEN, - sizeof(struct nss_if_open), nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - - /* - * Send the I/F up message to the decap interface. - */ - nss_status = nss_wifi_meshmgr_tx_msg_sync(wmesh_ctx, &wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh link decap I/F up failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_if_up); - -/* - * nss_wifi_meshmgr_dump_mesh_path() - * Dump mesh path table request asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_dump_mesh_path(nss_wifi_mesh_handle_t mesh_handle, nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - nss_wifi_meshmgr_status_t nss_status; - int32_t encap_ifnum; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the path dump request message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_WIFI_MESH_MSG_PATH_TABLE_DUMP, - sizeof(struct nss_wifi_mesh_path_table_dump), msg_cb, app_data); - - /* - * Send the path dump request mesage to the NSS asynchronously. - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh dump mesh path failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_dump_mesh_path); - -/* - * nss_wifi_meshmgr_dump_mesh_path_sync() - * Dump mesh path table request synchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_dump_mesh_path_sync(nss_wifi_mesh_handle_t mesh_handle) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - nss_wifi_meshmgr_status_t nss_status; - int32_t ret; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the path dump request mesage to the NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_dump_mesh_path(mesh_handle, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: WiFi mesh path dump msg failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_dump_mesh_path_sync); - -/* - * nss_wifi_meshmgr_dump_mesh_proxy_path() - * Dump mesh proxy path table request asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_dump_mesh_proxy_path(nss_wifi_mesh_handle_t mesh_handle, nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - nss_wifi_meshmgr_status_t nss_status; - int32_t encap_ifnum; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the proxy path table message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_WIFI_MESH_MSG_PROXY_PATH_TABLE_DUMP, - sizeof(struct nss_wifi_mesh_proxy_path_table_dump), msg_cb, app_data); - - /* - * Send the proxy path dump message to NSS asynchronously. - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh link vap proxy path dump failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_dump_mesh_proxy_path); - -/* - * nss_wifi_meshmgr_dump_mesh_path_sync() - * Dump mesh proxy path table request synchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_dump_mesh_proxy_path_sync(nss_wifi_mesh_handle_t mesh_handle) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - nss_wifi_meshmgr_status_t nss_status; - int32_t ret; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the path dump request to the NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_dump_mesh_proxy_path(mesh_handle, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: WiFi mesh proxy path dump msg failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_dump_mesh_proxy_path_sync); - -/* - * nss_wifi_meshmgr_assoc_link_vap() - * Associate the link interface to the mesh I/F asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_assoc_link_vap(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_assoc_link_vap *wmalv, - nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_vdev_msg *wifivdevmsg; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - struct nss_wifi_vdev_set_next_hop_msg *next_hop_msg = NULL; - int32_t decap_ifnum, link_ifnum; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - wifivdevmsg = kzalloc(sizeof(*wifivdevmsg), GFP_ATOMIC); - if (!wifivdevmsg) { - nss_wifi_meshmgr_warn("%px: Failed to allocate message memmory", &wmgr_ctx); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - decap_ifnum = wmesh_ctx->decap_ifnum; - - /* - * Verify the decap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(decap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_OUTER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, decap_ifnum); - kfree(wifivdevmsg); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - - link_ifnum = wmalv->link_vap_id; - - /* - * Verify the link VAP I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(link_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_VAP))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, link_ifnum); - kfree(wifivdevmsg); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - - next_hop_msg = &wifivdevmsg->msg.next_hop; - next_hop_msg->ifnumber = decap_ifnum; - nss_cmn_msg_init(&wifivdevmsg->cm, link_ifnum, NSS_WIFI_VDEV_SET_NEXT_HOP, sizeof(*next_hop_msg), - msg_cb, app_data); - - /* - * Send the link vap mesage to the NSS synchronously. - */ - nss_status = nss_wifi_vdev_tx_msg(wmgr_ctx.nss_ctx, wifivdevmsg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh link vap association failed: %d.\n", &wmgr_ctx, nss_status); - } - - kfree(wifivdevmsg); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_assoc_link_vap); - -/* - * nss_wifi_meshmgr_assoc_link_vap_sync() - * Associate the link VAP to the mesh I/F synchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_assoc_link_vap_sync(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_assoc_link_vap *wmalv) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - nss_wifi_meshmgr_status_t nss_status; - int32_t ret; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the link vap mesage to the NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_assoc_link_vap(mesh_handle, wmalv, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh link vap association failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_assoc_link_vap_sync); - -/* - * nss_wifi_meshmgr_mesh_config_update() - * Update mesh configuration message asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_config_update(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_config_msg *wmcum, - nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - struct nss_wifi_mesh_config_msg *nwmcum; - int32_t encap_ifnum, decap_ifnum; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - decap_ifnum = wmesh_ctx->decap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Verify the decap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(decap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_OUTER))) { - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, decap_ifnum); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the mesh configuration messsage. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nwmcum = &wmesh_msg.msg.mesh_config; - memcpy(nwmcum, wmcum, sizeof(*nwmcum)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_WIFI_MESH_MSG_INTERFACE_CONFIGURE, - sizeof(*nwmcum), msg_cb, app_data); - - /* - * Send the configuration message to encap I/F. - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh configuration message failed: %d.\n", &wmgr_ctx, nss_status); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Initialize the mesh configuration messsage. - */ - nss_wifi_mesh_msg_init(&wmesh_msg, decap_ifnum, NSS_WIFI_MESH_MSG_INTERFACE_CONFIGURE, - sizeof(*nwmcum), msg_cb, app_data); - - /* - * Send the configuration message decap I/F. - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh configuration message failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_config_update); - -/* - * nss_wifi_meshmgr_mesh_config_update_sync() - * Update mesh configuration message synchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_config_update_sync(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_config_msg *wmcum) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - nss_wifi_meshmgr_status_t nss_status; - int32_t ret; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the message to NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_mesh_config_update(mesh_handle, wmcum, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh proxy path update failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_config_update_sync); - -/* - * nss_wifi_meshmgr_mesh_proxy_path_delete() - * Delete the mesh proxy path asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_proxy_path_delete(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_proxy_path_del_msg *wmppdm, - nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - struct nss_wifi_mesh_proxy_path_del_msg *nwmppdm; - int32_t encap_ifnum; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nwmppdm = &wmesh_msg.msg.proxy_del_msg; - memcpy(nwmppdm, wmppdm, sizeof(*nwmppdm)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_WIFI_MESH_MSG_PROXY_PATH_DELETE, - sizeof(*nwmppdm), msg_cb, app_data); - - /* - * Send the message to NSS asynchronously. - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh proxy path delete failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_proxy_path_delete); - -/* - * nss_wifi_meshmgr_mesh_proxy_path_delete_sync() - * Delete the mesh proxy path synchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_proxy_path_delete_sync(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_proxy_path_del_msg *wmppdm) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - nss_wifi_meshmgr_status_t nss_status; - int32_t ret; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the message to NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_mesh_proxy_path_delete(mesh_handle, wmppdm, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh proxy path delete failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_proxy_path_delete_sync); - -/* - * nss_wifi_meshmgr_mesh_proxy_path_update() - * Mesh prpxy path update message asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_proxy_path_update(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_proxy_path_update_msg *wmppum, - nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - struct nss_wifi_mesh_proxy_path_update_msg *nwmppum; - int32_t encap_ifnum; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nwmppum = &wmesh_msg.msg.proxy_update_msg; - memcpy(nwmppum, wmppum, sizeof(*nwmppum)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_WIFI_MESH_MSG_PROXY_PATH_UPDATE, - sizeof(*nwmppum), msg_cb, app_data); - - /* - * Send the message to NSS asynchronously - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh proxy path update failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_proxy_path_update); - -/* - * nss_wifi_meshmgr_mesh_proxy_path_update_sync() - * Send proxy update message synchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_proxy_path_update_sync(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_proxy_path_update_msg *wmppum) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - nss_wifi_meshmgr_status_t nss_status; - int32_t ret; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the message to NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_mesh_proxy_path_update(mesh_handle, wmppum, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh proxy path update failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_proxy_path_update_sync); - -/* - * nss_wifi_meshmgr_mesh_proxy_path_add() - * Send mesh proxy add message asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_proxy_path_add(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_proxy_path_add_msg *wmppam, - nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - struct nss_wifi_mesh_proxy_path_add_msg *nwmppam; - int32_t encap_ifnum; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the message - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nwmppam = &wmesh_msg.msg.proxy_add_msg; - memcpy(nwmppam, wmppam, sizeof(*nwmppam)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_WIFI_MESH_MSG_PROXY_PATH_ADD, - sizeof(*nwmppam), msg_cb, app_data); - - /* - * Send the message to NSS asynchronously. - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh proxy path add failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_proxy_path_add); - -/* - * nss_wifi_meshmgr_mesh_proxy_path_add_sync() - * Send mesh proxy add message synchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_proxy_path_add_sync(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_proxy_path_add_msg *wmppam) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - int32_t ret; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the message to NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_mesh_proxy_path_add(mesh_handle, wmppam, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh proxy path add failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_proxy_path_add_sync); - -/* - * nss_wifi_meshmgr_mesh_path_delete() - * Send the mesh path delete message asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_path_delete(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_mpath_del_msg *wmpdm, - nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - struct nss_wifi_mesh_mpath_del_msg *nwmpdm; - int32_t encap_ifnum; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nwmpdm = &wmesh_msg.msg.mpath_del; - memcpy(nwmpdm, wmpdm, sizeof(*nwmpdm)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_WIFI_MESH_MSG_MPATH_DELETE, - sizeof(*nwmpdm), msg_cb, app_data); - - /* - * Send the message to NSS asynchronously. - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh path delete failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_path_delete); - -/* - * nss_wifi_meshmgr_mesh_path_delete_sync() - * Send the mesh path delete message synchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_path_delete_sync(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_mpath_del_msg *wmpdm) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - int32_t ret; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the message to NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_mesh_path_delete(mesh_handle, wmpdm, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh path delete failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_path_delete_sync); - -/* - * nss_wifi_meshmgr_mesh_path_add() - * Mesh path add message asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_path_add(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_mpath_add_msg *wmpam, - nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_mesh_mpath_add_msg *nwmpam; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - int32_t encap_ifnum; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nwmpam = &wmesh_msg.msg.mpath_add; - memcpy(nwmpam, wmpam, sizeof(*nwmpam)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_WIFI_MESH_MSG_MPATH_ADD, - sizeof(*nwmpam), msg_cb, app_data); - - /* - * Send the message to NSS asynchronously. - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh path addition failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_path_add); - -/* - * nss_wifi_meshmgr_mesh_path_add_sync() - * Mesh path add message synchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_path_add_sync(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_mpath_add_msg *wmpam) -{ - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - int32_t ret; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the message to NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_mesh_path_add(mesh_handle, wmpam, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh path addition failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_path_add_sync); - -/* - * nss_wifi_meshmgr_mpath_update() - * Send mesh path update message asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_path_update(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_mpath_update_msg *wmpum, - nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_mesh_mpath_update_msg *nwmpum; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - int32_t encap_ifnum; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the mesh path update message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nwmpum = &wmesh_msg.msg.mpath_update; - memcpy(nwmpum, wmpum, sizeof(*nwmpum)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_WIFI_MESH_MSG_MPATH_UPDATE, - sizeof(*nwmpum), msg_cb, app_data); - - /* - * Send the message to NSS asynchronously. - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh MPath update failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_path_update); - -/* - * nss_wifi_meshmgr_mpath_update_sync() - * Send mesh path update message sychronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_path_update_sync(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_mpath_update_msg *wmpum) -{ - nss_wifi_meshmgr_status_t nss_status; - int32_t ret; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the message to NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_mesh_path_update(mesh_handle, wmpum, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh MPath update failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_path_update_sync); - -/* - * nss_wifi_meshmgr_mesh_path_exception() - * Mesh path exception msg asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_path_exception(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_exception_flag_msg *wmefm, - nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_mesh_exception_flag_msg *nwmefm; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - int32_t encap_ifnum; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Initialize the message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nwmefm = &wmesh_msg.msg.exception_msg; - memcpy(nwmefm, wmefm, sizeof(*nwmefm)); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_WIFI_MESH_MSG_EXCEPTION_FLAG, - sizeof(*nwmefm), msg_cb, app_data); - - /* - * Send the message to NSS asynchronously. - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh path exception message failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_path_exception); - -/* - * nss_wifi_meshmgr_mesh_path_exception_sync() - * Send mesh path exception message sychronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_mesh_path_exception_sync(nss_wifi_mesh_handle_t mesh_handle,struct nss_wifi_mesh_exception_flag_msg *wmefm) -{ - nss_wifi_meshmgr_status_t nss_status; - int32_t ret; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the message to NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_mesh_path_exception(mesh_handle, wmefm, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh path exception message failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_mesh_path_exception_sync); - -/* - * nss_wifi_meshmgr_config_mesh_exception() - * Configure mesh exception asynchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_config_mesh_exception(nss_wifi_mesh_handle_t mesh_handle, struct nss_wifi_mesh_rate_limit_config *wmrlc, - nss_wifi_mesh_msg_callback_t msg_cb, void *app_data) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_mesh_rate_limit_config *nwmrlc; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - int32_t encap_ifnum, decap_ifnum, ifnum; - nss_wifi_meshmgr_status_t nss_status; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - decap_ifnum = wmesh_ctx->decap_ifnum; - - /* - * Verify the decap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(decap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_OUTER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, decap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - switch(wmrlc->exception_num) { - case NSS_WIFI_MESH_DS_MESH_PATH_NOT_FOUND: - ifnum = encap_ifnum; - break; - - case NSS_WIFI_MESH_US_MESH_PROXY_NOT_FOUND: - ifnum = decap_ifnum; - break; - - case NSS_WIFI_MESH_US_MESH_PATH_NOT_FOUND: - ifnum = decap_ifnum; - break; - } - - /* - * Initialize the message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nwmrlc = &wmesh_msg.msg.exc_cfg; - memcpy(nwmrlc, wmrlc, sizeof(*nwmrlc)); - nss_wifi_mesh_msg_init(&wmesh_msg, ifnum, NSS_WIFI_MESH_CONFIG_EXCEPTION, - sizeof(*nwmrlc), msg_cb, app_data); - - /* - * Send the message to NSS asynchronously. - */ - nss_status = nss_wifi_meshmgr_tx_msg(&wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh config exception message failed: %d.\n", &wmgr_ctx, nss_status); - } - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_config_mesh_exception); - -/* - * nss_wifi_meshmgr_config_mesh_exception_sync() - * Configure mesh exception synchronously. - */ -nss_wifi_meshmgr_status_t -nss_wifi_meshmgr_config_mesh_exception_sync(nss_wifi_mesh_handle_t mesh_handle,struct nss_wifi_mesh_rate_limit_config *wmrlc) -{ - nss_wifi_meshmgr_status_t nss_status; - int32_t ret; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_NULL_MESH_CTX; - } - - /* - * Send the message to NSS synchronously. - */ - down(&wmesh_ctx->sem); - nss_status = nss_wifi_meshmgr_config_mesh_exception(mesh_handle, wmrlc, nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Mesh config exception message failed: %d.\n", &wmgr_ctx, nss_status); - up(&wmesh_ctx->sem); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; - } - - /* - * Wait for the acknowledgement - */ - ret = wait_for_completion_timeout(&wmesh_ctx->complete, msecs_to_jiffies(NSS_WIFI_MESH_TX_TIMEOUT)); - if (!ret) { - nss_wifi_meshmgr_warn("%px: WiFi mesh msg tx failed due to timeout\n", &wmgr_ctx); - wmesh_ctx->response = NSS_WIFI_MESHMGR_FAILURE_SYNC_TIMEOUT; - } - - nss_status = wmesh_ctx->response; - up(&wmesh_ctx->sem); - - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_config_mesh_exception_sync); - -/* - * nss_wifi_meshmgr_if_destroy_sync() - * Function to unregister and destroy dynamic interfaces synchronously. - */ -nss_wifi_meshmgr_status_t nss_wifi_meshmgr_if_destroy_sync(nss_wifi_mesh_handle_t mesh_handle) -{ - int32_t encap_ifnum, decap_ifnum; - nss_wifi_meshmgr_status_t nss_status; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - - wmesh_ctx = nss_wifi_meshmgr_find_and_ref_inc(mesh_handle); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Mesh context is null\n", &wmgr_ctx); - return NSS_WIFI_MESHMGR_FAILURE_BAD_PARAM; - } - - encap_ifnum = wmesh_ctx->encap_ifnum; - decap_ifnum = wmesh_ctx->decap_ifnum; - - /* - * Verify the encap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, encap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Verify the decap I/F number against it types. - */ - if (!(nss_wifi_meshmgr_verify_if_num(decap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_OUTER))) { - nss_wifi_meshmgr_warn("%px: I/F num: 0x%x verification failed\n", &wmgr_ctx, decap_ifnum); - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return NSS_WIFI_MESHMGR_FAILURE; - } - - /* - * Send the I/F down message to NSS. - */ - nss_status = nss_wifi_meshmgr_if_down(mesh_handle); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Sending mesh I/F down to NSS failed: %d\n", &wmgr_ctx, nss_status); - } - - /* - * Remove mesh context from the table. - */ - spin_lock_bh(&wmgr_ctx.ref_lock); - nss_wifi_meshmgr_ctx_remove(wmesh_ctx); - wmgr_ctx.mesh_count--; - spin_unlock_bh(&wmgr_ctx.ref_lock); - - /* - * Release the reference taken during alloc. - */ - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - - /* - * Release the reference for the find taken at the beginning of the function. - */ - nss_wifi_meshmgr_ref_dec(wmesh_ctx); - return nss_status; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_if_destroy_sync); - -/* - * nss_wifi_meshmgr_if_create_sync() - * Create and register dynamic interface synchronously. - * - * Note: Synchronous create message, callbacks are used for driver registration not message handling. - */ -nss_wifi_mesh_handle_t nss_wifi_meshmgr_if_create_sync(struct net_device *dev, struct nss_wifi_mesh_config_msg *wmcm, - nss_wifi_mesh_data_callback_t data_cb, - nss_wifi_mesh_ext_data_callback_t ext_data_cb, - nss_wifi_mesh_msg_callback_t event_cb) -{ - struct nss_wifi_mesh_msg wmesh_msg; - struct nss_wifi_mesh_config_msg *nwmcm; - int32_t encap_ifnum, decap_ifnum; - uint32_t features = 0; - nss_wifi_mesh_handle_t mesh_handle; - nss_wifi_meshmgr_status_t nss_status; - struct nss_wifi_meshmgr_mesh_ctx *wmesh_ctx; - - spin_lock_bh(&wmgr_ctx.ref_lock); - if (wmgr_ctx.mesh_count == NSS_WIFI_MESH_MAX) { - nss_wifi_meshmgr_warn("%px: Reached maxed number of mesh interface\n", dev); - spin_unlock_bh(&wmgr_ctx.ref_lock); - return -1; - } - - wmgr_ctx.mesh_count++; - spin_unlock_bh(&wmgr_ctx.ref_lock); - - dev_hold(dev); - wmesh_ctx = kzalloc(sizeof(*wmesh_ctx), GFP_ATOMIC); - if (!wmesh_ctx) { - nss_wifi_meshmgr_warn("%px: Failed to allocate memory for mesh context\n", dev); - goto ctx_alloc_fail; - } - - wmesh_ctx->dev = dev; - sema_init(&wmesh_ctx->sem, 1); - init_completion(&wmesh_ctx->complete); - - /* - * Alloc the encap dynamic interface node. - */ - encap_ifnum = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER); - if (encap_ifnum < 0) { - nss_wifi_meshmgr_warn("%px: Encap allocation failed.\n", dev); - goto encap_alloc_fail; - } - - if (nss_register_wifi_mesh_if(encap_ifnum, data_cb, ext_data_cb, event_cb, - NSS_WIFI_MESH_DP_INNER, dev, features) != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Encap registration failed.\n", dev); - goto encap_reg_fail; - } - - /* - * Allocate and register decap interface. - */ - decap_ifnum = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_OUTER); - if (decap_ifnum < 0) { - nss_wifi_meshmgr_warn("%px: Decap allocation failed.\n", dev); - goto decap_alloc_fail; - } - - - if (nss_register_wifi_mesh_if(decap_ifnum, data_cb, ext_data_cb, event_cb, - NSS_WIFI_MESH_DP_OUTER, dev, features) != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Decap registration failed.\n", dev); - goto decap_reg_fail; - } - - wmesh_ctx->encap_ifnum = encap_ifnum; - wmesh_ctx->decap_ifnum = decap_ifnum; - - nss_wifi_meshmgr_trace("%px: Successfully registered encap and decap iface for Mesh\n", dev); - - /* - * Initialize the encap configuration message. - */ - memset(&wmesh_msg, 0, sizeof(struct nss_wifi_mesh_msg)); - nwmcm = &wmesh_msg.msg.mesh_config; - nwmcm->ttl = wmcm->ttl; - nwmcm->mesh_path_refresh_time = wmcm->mesh_path_refresh_time; - nwmcm->mpp_learning_mode = wmcm->mpp_learning_mode; - nwmcm->config_flags = wmcm->config_flags | NSS_WIFI_MESH_CONFIG_FLAG_SIBLING_IF_NUM_VALID; - nwmcm->sibling_ifnum = decap_ifnum; - - ether_addr_copy(nwmcm->local_mac_addr, wmcm->local_mac_addr); - nss_wifi_mesh_msg_init(&wmesh_msg, encap_ifnum, NSS_WIFI_MESH_MSG_INTERFACE_CONFIGURE, - sizeof(*nwmcm), nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - - /* - * Send the encap configuration message. - */ - nss_status = nss_wifi_meshmgr_tx_msg_sync(wmesh_ctx, &wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Encap configuration message failed: %d.\n", dev, nss_status); - goto config_failed; - } - - /* - * Initialize the decap configuration message. - */ - nwmcm->sibling_ifnum = encap_ifnum; - nwmcm->block_mesh_forwarding = wmcm->block_mesh_forwarding; - nss_wifi_mesh_msg_init(&wmesh_msg, decap_ifnum, NSS_WIFI_MESH_MSG_INTERFACE_CONFIGURE, - sizeof(*nwmcm), nss_wifi_meshmgr_tx_msg_cb, wmesh_ctx); - - /* - * Send the decap configuration message. - */ - nss_status = nss_wifi_meshmgr_tx_msg_sync(wmesh_ctx, &wmesh_msg); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Decap configuration message failed: %d.\n", dev, nss_status); - goto config_failed; - } - - /* - * Take the self reference on the mesh context. - */ - atomic_set(&wmesh_ctx->ref, 1); - - /* - * Add the Mesh context to the mesh manager's list. - */ - spin_lock_bh(&wmgr_ctx.ref_lock); - mesh_handle = nss_wifi_meshmgr_ctx_insert(wmesh_ctx); - if (mesh_handle < 0) { - spin_unlock_bh(&wmgr_ctx.ref_lock); - nss_wifi_meshmgr_warn("%px: Insertion for mesh context failed", &wmgr_ctx); - goto config_failed; - } - - spin_unlock_bh(&wmgr_ctx.ref_lock); - - nss_wifi_meshmgr_trace("%px: WiFi Mesh interface count:%d.\n", dev, wmgr_ctx.mesh_count); - return mesh_handle; - -config_failed: - nss_unregister_wifi_mesh_if(decap_ifnum); -decap_reg_fail: - nss_dynamic_interface_dealloc_node(decap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_OUTER); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Decap interface dealloc failed: %d\n", dev, nss_status); - } -decap_alloc_fail: - nss_unregister_wifi_mesh_if(encap_ifnum); -encap_reg_fail: - nss_dynamic_interface_dealloc_node(encap_ifnum, NSS_DYNAMIC_INTERFACE_TYPE_WIFI_MESH_INNER); - if (nss_status != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px: Encap interface dealloc failed: %d\n", dev, nss_status); - } -encap_alloc_fail: - kfree(wmesh_ctx); -ctx_alloc_fail: - spin_lock_bh(&wmgr_ctx.ref_lock); - wmgr_ctx.mesh_count--; - spin_unlock_bh(&wmgr_ctx.ref_lock); - dev_put(dev); - return -1; -} -EXPORT_SYMBOL(nss_wifi_meshmgr_if_create_sync); - -/* - * nss_wifi_meshmgr_exit_module() - * WiFi-Mesh module exit function - */ -static void __exit nss_wifi_meshmgr_exit_module(void) -{ - int32_t i; - - /* - * Check if there are any mesh I/F. Delete all the mesh I/F from NSS FW and free. - */ - for (i = 0; i < NSS_WIFI_MESH_MAX; i++) { - if (nss_wifi_meshmgr_if_destroy_sync(i) != NSS_WIFI_MESHMGR_SUCCESS) { - nss_wifi_meshmgr_warn("%px Destroy failed or context does not exist", &wmgr_ctx); - } - } - nss_wifi_meshmgr_info("Module %s unloaded\n", NSS_CLIENT_BUILD_ID); -} - -/* - * nss_wifi_meshmgr_init_module() - * Wi-Fi mesh manager module init function - */ -static int __init nss_wifi_meshmgr_init_module(void) -{ - struct nss_ctx_instance *nss_ctx; - int32_t idx; - -#ifdef CONFIG_OF - /* - * If the node is not compatible, don't do anything. - */ - if (!of_find_node_by_name(NULL, "nss-common")) { - nss_wifi_meshmgr_warn("NSS common not found.\n"); - return -1; - } -#endif - - nss_ctx = nss_wifi_mesh_get_context(); - if (!nss_ctx) { - nss_wifi_meshmgr_warn("NSS SoC context is NULL.\n"); - return -1; - } - - wmgr_ctx.nss_ctx = nss_ctx; - for (idx = 0; idx < NSS_WIFI_MESH_MAX; idx++) { - wmgr_ctx.mesh_ctx[idx] = NULL; - } - - wmgr_ctx.mesh_count = 0; - spin_lock_init(&wmgr_ctx.ref_lock); - - nss_wifi_meshmgr_info("Module %s loaded\n", NSS_CLIENT_BUILD_ID); - return 0; -} - -module_init(nss_wifi_meshmgr_init_module); -module_exit(nss_wifi_meshmgr_exit_module); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("NSS WiFi-Mesh manager");