Merge "Set DMA direction to TO_DEVICE for Tx completions"
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 6549a84..9d34dbb 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -75,7 +75,7 @@
#define NSS_MAX_VIRTUAL_INTERFACES 16
#define NSS_MAX_TUNNEL_INTERFACES 4
#define NSS_MAX_SPECIAL_INTERFACES 24
-#define NSS_MAX_DYNAMIC_INTERFACES 3
+#define NSS_MAX_DYNAMIC_INTERFACES 8
/**
* Start of individual interface groups
@@ -369,7 +369,6 @@
#define NSS_IPV6_CREATE_FLAG_VLAN_MARKING 0x10
/** Rule for VLAN marking */
-
/**
* Structure to be used while sending an IPv6 flow/connection destroy rule.
*/
diff --git a/exports/nss_dynamic_interface.h b/exports/nss_dynamic_interface.h
index c82a3b3..79d8582 100644
--- a/exports/nss_dynamic_interface.h
+++ b/exports/nss_dynamic_interface.h
@@ -29,6 +29,7 @@
NSS_DYNAMIC_INTERFACE_TYPE_NONE = 0,
NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR = 1, /* GRE_REDIR Interface type */
NSS_DYNAMIC_INTERFACE_TYPE_CAPVAPV1 = 2, /* CAPVAPV1 Interface type */
+ NSS_DYNAMIC_INTERFACE_TYPE_TUN6RD = 3, /* TUN6RD Interface type */
NSS_DYNAMIC_INTERFACE_TYPE_MAX
};
@@ -51,4 +52,13 @@
*/
extern nss_tx_status_t nss_dynamic_interface_dealloc_node(int if_num, enum nss_dynamic_interface_type type);
+/**
+ * @brief The inferface number belong to the dynamic interface
+ *
+ * @param if_num interface number of dynamic interface
+ *
+ * @return bool true or false
+ */
+bool nss_is_dynamic_interface(int if_num);
+
#endif /* __NSS_DYNAMIC_INTERFACE_H*/
diff --git a/exports/nss_ipsec.h b/exports/nss_ipsec.h
index e5061af..b94bc3a 100644
--- a/exports/nss_ipsec.h
+++ b/exports/nss_ipsec.h
@@ -27,7 +27,7 @@
* refer http://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml
* for the full list
*/
-#define NSS_IPSEC_ARPHRD_IPSEC 0x31 /**< iana.org ARP Hardware type for IPsec tunnel*/
+#define NSS_IPSEC_ARPHRD_IPSEC 31 /**< iana.org ARP Hardware type for IPsec tunnel*/
#define NSS_IPSEC_MAX_SA 256 /**< maximum SAs supported */
#if (~(NSS_IPSEC_MAX_SA - 1) & (NSS_IPSEC_MAX_SA >> 1))
@@ -106,11 +106,12 @@
uint8_t cipher_algo; /**< Cipher algorithm */
uint8_t auth_algo; /**< Authentication algorithm */
- uint8_t esp_seq_skip; /**< Skip ESP sequence number */
+ uint8_t nat_t_req; /**< NAT-T required */
uint8_t esp_icv_len; /**< ESP trailers ICV length to apply */
- uint8_t nat_t_req; /**< NAT-T required */
- uint8_t res[3]; /**< Reserve bytes for alignment */
+ uint8_t esp_seq_skip; /**< Skip ESP sequence number */
+ uint8_t esp_tail_skip; /**< Skip ESP trailer */
+ uint8_t res[2]; /**< Reserve bytes for alignment */
};
/*
@@ -192,6 +193,16 @@
extern nss_tx_status_t nss_ipsec_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_ipsec_msg *msg);
/**
+ * @brief send an IPsec process request
+ *
+ * @param os_buf Data buffer
+ * @param if_num NSS interface number
+ *
+ * @return Status
+ */
+extern nss_tx_status_t nss_ipsec_tx_buf(struct sk_buff *os_buf, uint32_t if_num);
+
+/**
* @brief register a event callback handler with HLOS driver
*
* @param if_num[IN] receive events from this interface (Encap, Decap or C2C)
diff --git a/exports/nss_ipsecmgr.h b/exports/nss_ipsecmgr.h
index f53f4b2..7bbfe5b 100644
--- a/exports/nss_ipsecmgr.h
+++ b/exports/nss_ipsecmgr.h
@@ -42,6 +42,8 @@
#define NSS_IPSECMGR_TUN_MTU(x) (x - NSS_IPSECMGR_TUN_MAX_HDR_LEN)
+#define NSS_IPSECMGR_NATT_PORT_DATA 4500
+
/**
* @brief Definition of an IPsec encapsulation rule for an add operation
*/
@@ -67,7 +69,8 @@
uint8_t esp_icv_len; /**< ESP trailer's ICV length */
uint8_t esp_seq_skip; /**< Skip ESP sequence number in header*/
- uint8_t res[3]; /**< reserve for 4-byte alignment */
+ uint8_t esp_tail_skip; /**< Skip ESP trailer*/
+ uint8_t res[2]; /**< reserve for 4-byte alignment */
};
/**
@@ -100,6 +103,10 @@
uint8_t auth_algo; /**< Authentication algorithm */
uint8_t esp_icv_len; /**< ESP trailer's ICV length */
uint8_t nat_t_req; /**< Remove NAT-T header */
+
+ uint8_t esp_seq_skip; /**< Skip ESP sequence number in header*/
+ uint8_t esp_tail_skip; /**< Skip ESP trailer*/
+ uint8_t res[2]; /**< reserve for 4-byte alignment */
};
/**
diff --git a/exports/nss_ipv4.h b/exports/nss_ipv4.h
index 24a7da4..595593a 100644
--- a/exports/nss_ipv4.h
+++ b/exports/nss_ipv4.h
@@ -36,6 +36,7 @@
NSS_IPV4_RX_ESTABLISH_RULE_MSG, /**< IPv4 establish rule message */
NSS_IPV4_RX_CONN_STATS_SYNC_MSG, /**< IPv4 connection stats sync message */
NSS_IPV4_RX_NODE_STATS_SYNC_MSG, /**< IPv4 generic statistics sync message */
+ NSS_IPV4_TX_CONN_CFG_RULE_MSG, /**< IPv4 number of connections supported rule message */
NSS_IPV4_MAX_MSG_TYPES, /**< IPv4 message max type number */
};
@@ -187,6 +188,14 @@
};
/**
+ * The IPv4 rule number of supported connections sub-message structure.
+ */
+struct nss_ipv4_rule_conn_cfg_msg {
+ uint32_t num_conn; /**< Number of supported IPv4 connections */
+};
+
+
+/**
* The NSS IPv4 rule establish structure.
*/
struct nss_ipv4_rule_establish {
@@ -373,6 +382,7 @@
struct nss_ipv4_rule_establish rule_establish; /**< Message: rule establish confirmation */
struct nss_ipv4_conn_sync conn_stats; /**< Message: connection stats sync */
struct nss_ipv4_node_sync node_stats; /**< Message: node stats sync */
+ struct nss_ipv4_rule_conn_cfg_msg rule_conn_cfg; /**< Message: rule connections supported */
} msg;
};
@@ -422,4 +432,18 @@
*/
extern void nss_ipv4_register_handler(void);
+/**
+ * @brief IPv4 sysctl register
+ *
+ * @return None
+ */
+extern void nss_ipv4_register_sysctl(void);
+
+/**
+ * @brief IPv4 sysctl unregister
+ *
+ * @return None
+ */
+extern void nss_ipv4_unregister_sysctl(void);
+
#endif /* __NSS_IPV4_H */
diff --git a/exports/nss_ipv6.h b/exports/nss_ipv6.h
index e08513a..7535e66 100644
--- a/exports/nss_ipv6.h
+++ b/exports/nss_ipv6.h
@@ -36,6 +36,7 @@
NSS_IPV6_RX_ESTABLISH_RULE_MSG, /**< IPv6 establish rule message */
NSS_IPV6_RX_CONN_STATS_SYNC_MSG, /**< IPv6 connection stats sync message */
NSS_IPV6_RX_NODE_STATS_SYNC_MSG, /**< IPv6 generic statistics sync message */
+ NSS_IPV6_TX_CONN_CFG_RULE_MSG, /**< IPv6 connection cfg rule message */
NSS_IPV6_MAX_MSG_TYPES,
};
@@ -225,6 +226,13 @@
};
/**
+ * The IPv6 rule conn cfgsub-message structure.
+ */
+struct nss_ipv6_rule_conn_cfg_msg {
+ uint32_t num_conn; /**< Holds number of supported connections in IPv6 */
+};
+
+/**
* The NSS IPv6 rule establish structure.
*/
struct nss_ipv6_rule_establish {
@@ -344,6 +352,7 @@
struct nss_ipv6_rule_establish rule_establish; /**< Message: rule establish confirmation */
struct nss_ipv6_conn_sync conn_stats; /**< Message: stats sync */
struct nss_ipv6_node_sync node_stats; /**< Message: node stats sync */
+ struct nss_ipv6_rule_conn_cfg_msg rule_conn_cfg;/**< Message: rule conn cfg */
} msg;
};
@@ -392,4 +401,20 @@
* @return none
*/
extern void nss_ipv6_register_handler(void);
+
+/**
+ * @brief IPv4 sysctl register
+ *
+ * @return None
+ */
+extern void nss_ipv6_register_sysctl(void);
+
+/**
+ * @brief IPv4 sysctl unregister
+ *
+ * @return None
+ */
+extern void nss_ipv6_unregister_sysctl(void);
+
+
#endif /* __NSS_IPV6_H */
diff --git a/exports/nss_tun6rd.h b/exports/nss_tun6rd.h
index cf58fa1..98b9bea 100644
--- a/exports/nss_tun6rd.h
+++ b/exports/nss_tun6rd.h
@@ -30,50 +30,51 @@
* 6rd tunnel request/response types
*/
enum nss_tun6rd_metadata_types {
- NSS_TUN6RD_TX_IF_CREATE,
- NSS_TUN6RD_TX_IF_DESTROY,
+ NSS_TUN6RD_ATTACH_PNODE,
NSS_TUN6RD_RX_STATS_SYNC,
+ NSS_TUN6RD_ADD_UPDATE_PEER,
NSS_TUN6RD_MAX,
};
/**
* 6rd tunnel configuration message structure
*/
-struct nss_tun6rd_create_msg {
- uint32_t prefix[4]; /* 6rd prefix */
- uint32_t relay_prefix; /* Relay prefix */
- uint16_t prefixlen; /* 6rd prefix len */
- uint16_t relay_prefixlen;/* Relay prefix length*/
+struct nss_tun6rd_attach_tunnel_msg {
+ uint32_t prefix[4]; /* 6rd prefix */
+ uint32_t relay_prefix; /* Relay prefix */
+ uint16_t prefixlen; /* 6rd prefix len */
+ uint16_t relay_prefixlen; /* Relay prefix length*/
uint32_t saddr; /* Tunnel source address */
uint32_t daddr; /* Tunnel destination addresss */
- uint8_t tos; /* Tunnel tos field */
- uint8_t ttl; /* Tunnel ttl field */
- uint16_t reserved; /* Reserved field */
-};
-
-/**
- * 6rd tunnel interface down message structure
- */
-struct nss_tun6rd_destroy_msg {
- uint32_t prefix[4]; /* Place holder */
+ uint8_t tos; /* Tunnel tos field */
+ uint8_t ttl; /* Tunnel ttl field */
+ uint16_t reserved; /* Reserved field */
};
/**
* 6rd tunnel statistics sync message structure.
*/
-struct nss_tun6rd_stats_sync_msg {
- struct nss_cmn_node_stats node_stats;
+struct nss_tun6rd_sync_stats_msg {
+ struct nss_cmn_node_stats node_stats; /* Node statstics*/
+};
+
+/**
+ * 6rd tunnel peer addr.
+ */
+struct nss_tun6rd_set_peer_msg {
+ uint32_t ipv6_address[4]; /* The peer's ipv6 addr*/
+ uint32_t dest; /* The peer's ipv4 addr*/
};
/**
* Message structure to send/receive 6rd tunnel messages
*/
struct nss_tun6rd_msg {
- struct nss_cmn_msg cm; /* Message Header */
+ struct nss_cmn_msg cm; /* Message Header */
union {
- struct nss_tun6rd_create_msg tun6rd_create; /* Message: Create 6rd tunnel */
- struct nss_tun6rd_destroy_msg tun6rd_destroy; /* Message: Destroy 6rd tunnel */
- struct nss_tun6rd_stats_sync_msg stats_sync; /* Message: interface stats sync */
+ struct nss_tun6rd_attach_tunnel_msg tunnel; /* Message: Attach 6rd tunnel */
+ struct nss_tun6rd_sync_stats_msg stats; /* Message: interface stats sync */
+ struct nss_tun6rd_set_peer_msg peer; /* Message: add/update peer */
} msg;
};
@@ -98,10 +99,17 @@
extern nss_tx_status_t nss_tun6rd_tx(struct nss_ctx_instance *nss_ctx, struct nss_tun6rd_msg *msg);
/**
+ * @brief Get the tun6rd context used in the nss_tun6rd_tx
+ *
+ * @return struct nss_ctx_instance *NSS context
+ */
+extern struct nss_ctx_instance *nss_tun6rd_get_context(void);
+
+/**
* @brief Callback to receive 6rd tunnel data
*
* @param app_data Application context of the message
- * @param os_buf Pointer to data buffer
+ * @param os_buf Pointer to data buffer
*
* @return void
*/
@@ -118,7 +126,7 @@
* @return nss_ctx_instance* NSS context
*/
extern struct nss_ctx_instance *nss_register_tun6rd_if(uint32_t if_num, nss_tun6rd_callback_t tun6rd_callback,
- nss_tun6rd_msg_callback_t msg_callback, struct net_device *netdev);
+ nss_tun6rd_msg_callback_t msg_callback, struct net_device *netdev);
/**
* @brief Unregister 6rd tunnel interface with NSS
diff --git a/nss_connmgr_tun6rd.c b/nss_connmgr_tun6rd.c
index 2a52087..801dc43 100644
--- a/nss_connmgr_tun6rd.c
+++ b/nss_connmgr_tun6rd.c
@@ -31,6 +31,7 @@
#include <net/ipip.h>
#include <linux/if_arp.h>
#include <nss_api_if.h>
+#include <nss_dynamic_interface.h>
/*
* NSS tun6rd debug macros
@@ -38,46 +39,40 @@
#if (NSS_TUN6RD_DEBUG_LEVEL < 1)
#define nss_tun6rd_assert(fmt, args...)
#else
-#define nss_tun6d_assert(c) if (!(c)) { BUG_ON(!(c)); }
+#define nss_tun6rd_assert(c) if (!(c)) { BUG_ON(!(c)); }
#endif
-#if (NSS_TUN6RD_DEBUG_LEVEL < 2)
-#define nss_tun6rd_error(fmt, args...)
+#if defined(CONFIG_DYNAMIC_DEBUG)
+/*
+ * Compile messages for dynamic enable/disable
+ */
+#define nss_tun6rd_warning(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define nss_tun6rd_info(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define nss_tun6rd_trace(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
-#define nss_tun6rd_error(fmt, args...) printk(KERN_WARNING "nss tun6rd:"fmt, ##args)
+
+/*
+ * Statically compile messages at different levels
+ */
+#if (NSS_TUN6RD_DEBUG_LEVEL < 2)
+#define nss_tun6rd_warning(s, ...)
+#else
+#define nss_tun6rd_warning(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
#if (NSS_TUN6RD_DEBUG_LEVEL < 3)
-#define nss_tun6rd_warning(fmt, args...)
+#define nss_tun6rd_info(s, ...)
#else
-#define nss_tun6rd_warning(fmt, args...) printk(KERN_WARNING "nss tun6rd:"fmt, ##args)
+#define nss_tun6rd_info(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
#if (NSS_TUN6RD_DEBUG_LEVEL < 4)
-#define nss_tun6rd_info(fmt, args...)
+#define nss_tun6rd_trace(s, ...)
#else
-#define nss_tun6rd_info(fmt, args...) printk(KERN_INFO "nss tun6rd :"fmt, ##args)
+#define nss_tun6rd_trace(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
-
-#if (NSS_TUN6RD_DEBUG_LEVEL < 5)
-#define nss_tun6rd_trace(fmt, args...)
-#else
-#define nss_tun6rd_trace(fmt, args...) printk(KERN_DEBUG "nss tun6rd :"fmt, ##args)
#endif
-void nss_tun6rd_exception(void *ctx, void *buf, __attribute__((unused)) struct napi_struct *napi);
-void nss_tun6rd_event_receive(void *ctx, struct nss_tun6rd_msg *msg);
-
-/*
- * 6rd tunnel host instance
- */
-struct nss_tun6rd_tunnel{
- struct nss_ctx_instance *nss_ctx;
- uint32_t if_num;
- struct net_device *netdev;
- uint32_t device_up;
-};
-
/*
* 6rd tunnel stats
*/
@@ -88,45 +83,106 @@
uint32_t tx_bytes; /* Number of transmitted bytes */
};
+/*
+ * nss_tun6rd_update_dev_stats
+ * Update the Dev stats received from NetAp
+ */
+static void nss_tun6rd_update_dev_stats(struct net_device *dev,
+ struct nss_tun6rd_sync_stats_msg *sync_stats)
+{
+ struct nss_tun6rd_stats stats;
-struct nss_tun6rd_tunnel g_tun6rd;
+ 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;
+
+ ipip6_update_offload_stats(dev, (void *)&stats);
+}
/*
- * Internal function
+ * nss_tun6rd_event_receive()
+ * Event Callback to receive events from NSS
*/
-static int
-nss_tun6rd_dev_event(struct notifier_block *nb,
- unsigned long event,
- void *dev);
+static void nss_tun6rd_event_receive(void *if_ctx, struct nss_tun6rd_msg *tnlmsg)
+{
+ struct net_device *netdev = if_ctx;
+
+ switch (tnlmsg->cm.type) {
+ case NSS_TUN6RD_RX_STATS_SYNC:
+ nss_tun6rd_update_dev_stats(netdev, (struct nss_tun6rd_sync_stats_msg *)&tnlmsg->msg.stats);
+ break;
+
+ default:
+ nss_tun6rd_info("Unknown Event from NSS\n");
+ break;
+ }
+}
/*
- * Linux Net device Notifier
+ * nss_tun6rd_exception()
+ * Exception handler registered to NSS driver
*/
-struct notifier_block nss_tun6rd_notifier = {
- .notifier_call = nss_tun6rd_dev_event,
-};
+static void nss_tun6rd_exception(void *ctx, void *buf, __attribute__((unused)) struct napi_struct *napi)
+{
+ struct net_device *dev = (struct net_device *)ctx;
+ struct sk_buff *skb = (struct sk_buff *)buf;
+ const struct iphdr *iph;
+
+ skb->dev = dev;
+ nss_tun6rd_info("received - %d bytes name %s ver %x\n",
+ skb->len,dev->name,skb->data[0]);
+
+ iph = (const struct iphdr *)skb->data;
+
+ /*
+ * Packet after Decap/Encap Did not find the Rule.
+ */
+ if (iph->version != 4) {
+ skb->protocol = htons(ETH_P_IPV6);
+ } else {
+ if (iph->protocol == IPPROTO_IPV6) {
+ skb_pull(skb, sizeof(struct iphdr));
+ skb->protocol = htons(ETH_P_IPV6);
+ skb_reset_network_header(skb);
+ skb->pkt_type = PACKET_HOST;
+ skb->ip_summed = CHECKSUM_NONE;
+ dev_queue_xmit(skb);
+ return;
+ }
+ 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_tun6rd_dev_up()
* 6RD Tunnel device i/f up handler
*/
-void nss_tun6rd_dev_up( struct net_device * netdev)
+static int nss_tun6rd_dev_up(struct net_device *netdev)
{
struct ip_tunnel *tunnel;
struct ip_tunnel_6rd_parm *ip6rd;
const struct iphdr *tiph;
struct nss_tun6rd_msg tun6rdmsg;
- struct nss_tun6rd_create_msg *tun6rdcfg;
+ struct nss_tun6rd_attach_tunnel_msg *tun6rdcfg;
+ uint32_t if_number;
nss_tx_status_t status;
+ struct nss_ctx_instance *nss_ctx;
/*
* Validate netdev for ipv6-in-ipv4 Tunnel
*/
- if (netdev->type != ARPHRD_SIT ) {
- return;
+ if (netdev->type != ARPHRD_SIT) {
+ return NOTIFY_BAD;
}
- tunnel = (struct ip_tunnel*)netdev_priv(netdev);
+ tunnel = (struct ip_tunnel *)netdev_priv(netdev);
ip6rd = &tunnel->ip6rd;
/*
@@ -139,16 +195,14 @@
if ((ip6rd->prefixlen == 0 )
|| (ip6rd->relay_prefixlen > 32)
|| (ip6rd->prefixlen
- + (32 - ip6rd->relay_prefixlen) > 64)){
+ + (32 - ip6rd->relay_prefixlen) > 64)) {
- nss_tun6rd_error("Invalid 6rd argument prefix len %d \
- relayprefix len %d \n",
+ nss_tun6rd_warning("Invalid 6rd argument prefix len %d relayprefix len %d \n",
ip6rd->prefixlen,ip6rd->relay_prefixlen);
- return;
+ return NOTIFY_BAD;
}
- nss_tun6rd_info(" Valid 6rd Tunnel Prefix %x %x %x %x \n \
- prefix len %d relay_prefix %d relay_prefixlen %d \n",
+ nss_tun6rd_info("Valid 6rd Tunnel Prefix %x %x %x %x\n Prefix len %d relay_prefix %d relay_prefixlen %d \n",
ip6rd->prefix.s6_addr32[0],ip6rd->prefix.s6_addr32[1],
ip6rd->prefix.s6_addr32[2],ip6rd->prefix.s6_addr32[3],
ip6rd->prefixlen, ip6rd->relay_prefix,
@@ -158,41 +212,42 @@
* Find the Tunnel device IP header info
*/
tiph = &tunnel->parms.iph ;
- nss_tun6rd_trace(" Tunnel Param srcaddr %x daddr %x ttl %d tos %x\n",
+ nss_tun6rd_trace("Tunnel Param srcaddr %x daddr %x ttl %d tos %x\n",
tiph->saddr, tiph->daddr,tiph->ttl,tiph->tos);
- if(tiph->saddr == 0) {
- nss_tun6rd_error("Tunnel src address not configured %x\n",
+ if (tiph->saddr == 0) {
+ nss_tun6rd_warning("Tunnel src address not configured %x\n",
tiph->saddr);
- return;
+ return NOTIFY_BAD;
}
- if (tiph->daddr == 0) {
- nss_tun6rd_error("Tunnel dest address not configured %x\n",
- tiph->daddr);
- return;
+ if_number = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_TUN6RD);
+ if (-1 == if_number) {
+ nss_tun6rd_warning("Request interface number failed\n");
+ return NOTIFY_BAD;
}
/*
* Register 6rd tunnel with NSS
*/
- g_tun6rd.nss_ctx = nss_register_tun6rd_if(g_tun6rd.if_num,
+ nss_ctx = nss_register_tun6rd_if(if_number,
nss_tun6rd_exception,
nss_tun6rd_event_receive,
netdev);
- if (g_tun6rd.nss_ctx == NULL) {
- nss_tun6rd_trace("nss_register_tun6rd_if Failed \n");
- return;
+ if (!nss_ctx) {
+ status = nss_dynamic_interface_dealloc_node(if_number, NSS_DYNAMIC_INTERFACE_TYPE_TUN6RD);
+ if (status != NSS_TX_SUCCESS) {
+ nss_tun6rd_warning("Unable to dealloc the node[%d] in the NSS fw!\n", if_number);
+ }
+ nss_tun6rd_trace("nss_register_tun6rd_if failed \n");
+ return NOTIFY_BAD;
}
- nss_tun6rd_trace("nss_register_tun6rd_if Success \n");
-
/*
* Prepare The Tunnel configuration parameter to send to nss
*/
memset(&tun6rdmsg, 0, sizeof(struct nss_tun6rd_msg));
- tun6rdcfg = &tun6rdmsg.msg.tun6rd_create;
-
+ tun6rdcfg = &tun6rdmsg.msg.tunnel;
tun6rdcfg->prefixlen = ip6rd->prefixlen;
tun6rdcfg->relay_prefix = ip6rd->relay_prefix;
tun6rdcfg->relay_prefixlen = ip6rd->relay_prefixlen;
@@ -205,61 +260,68 @@
tun6rdcfg->ttl = tiph->ttl;
tun6rdcfg->tos = tiph->tos;
- nss_tun6rd_trace(" 6rd Tunnel info \n");
- nss_tun6rd_trace(" saddr %x daddr %d ttl %x tos %x \n",
+ nss_tun6rd_trace(" 6rd Tunnel info\n");
+ nss_tun6rd_trace(" saddr %x daddr %d ttl %x tos %x\n",
tiph->saddr, tiph->daddr, tiph->ttl, tiph->tos);
- nss_tun6rd_trace(" Prefix %x:%x:%x:%x Prefix len %d \n",
+ nss_tun6rd_trace(" Prefix %x:%x:%x:%x Prefix len %d\n",
ip6rd->prefix.s6_addr32[0], ip6rd->prefix.s6_addr32[1],
ip6rd->prefix.s6_addr32[2], ip6rd->prefix.s6_addr32[3],
ip6rd->prefixlen);
nss_tun6rd_trace("Relay Prefix %x Len %d\n",
ip6rd->relay_prefix, ip6rd->relay_prefixlen);
- nss_tun6rd_trace("Sending 6rd tunnel i/f up command to NSS %x \n",
- (int)g_tun6rd.nss_ctx);
+ nss_tun6rd_trace("Sending 6rd tunnel i/f up command to NSS %x\n",
+ (int)nss_ctx);
/*
* Send 6rd Tunnel UP command to NSS
*/
- nss_cmn_msg_init(&tun6rdmsg.cm, NSS_TUN6RD_INTERFACE, NSS_TUN6RD_TX_IF_CREATE,
- sizeof(struct nss_tun6rd_create_msg), NULL, NULL);
+ nss_cmn_msg_init(&tun6rdmsg.cm, if_number, NSS_TUN6RD_ATTACH_PNODE,
+ sizeof(struct nss_tun6rd_attach_tunnel_msg), NULL, NULL);
- status = nss_tun6rd_tx(g_tun6rd.nss_ctx, &tun6rdmsg);
+ status = nss_tun6rd_tx(nss_ctx, &tun6rdmsg);
if (status != NSS_TX_SUCCESS) {
- nss_tun6rd_error("Tunnel up command error %d \n", status);
- return;
+ nss_unregister_tun6rd_if(if_number);
+ status = nss_dynamic_interface_dealloc_node(if_number, NSS_DYNAMIC_INTERFACE_TYPE_TUN6RD);
+ if (status != NSS_TX_SUCCESS) {
+ nss_tun6rd_warning("Unable to dealloc the node[%d] in the NSS fw!\n", if_number);
+ }
+ nss_tun6rd_warning("Tunnel up command error %d\n", status);
+ return NOTIFY_BAD;
}
- g_tun6rd.device_up = 1;
+ return NOTIFY_DONE;
}
/*
* nss_tun6rd_dev_down()
* 6RD Tunnel device i/f down handler
*/
-void nss_tun6rd_dev_down(struct net_device *netdev)
+static int nss_tun6rd_dev_down(struct net_device *netdev)
{
struct ip_tunnel *tunnel;
struct ip_tunnel_6rd_parm *ip6rd;
- struct nss_tun6rd_msg tun6rdmsg;
- struct nss_tun6rd_destroy_msg *tun6rdcfg;
+ int32_t if_number;
nss_tx_status_t status;
/*
- * Check if tunnel 6rd is registered ?
- */
- if (g_tun6rd.nss_ctx == NULL) {
- return;
- }
-
- /*
* Validate netdev for ipv6-in-ipv4 Tunnel
*/
- if (netdev->type != ARPHRD_SIT ) {
- return;
+ if (netdev->type != ARPHRD_SIT) {
+ return NOTIFY_BAD;
}
- tunnel = (struct ip_tunnel*)netdev_priv(netdev);
+ /*
+ * Check if tunnel 6rd is registered ?
+ */
+ if_number = nss_cmn_get_interface_number_by_dev(netdev);
+ if (if_number < 0) {
+ nss_tun6rd_warning("Net device:%p is not registered \n",netdev);
+ return NOTIFY_BAD;
+ }
+
+
+ tunnel = (struct ip_tunnel *)netdev_priv(netdev);
ip6rd = &tunnel->ip6rd;
/*
@@ -268,53 +330,27 @@
if ((ip6rd->prefixlen == 0 )
|| (ip6rd->relay_prefixlen > 32 )
|| (ip6rd->prefixlen
- + (32 - ip6rd->relay_prefixlen) > 64)){
+ + (32 - ip6rd->relay_prefixlen) > 64)) {
- nss_tun6rd_error("Invalid 6rd argument prefix len %d \
- relayprefix len %d \n",
+ nss_tun6rd_warning("Invalid 6rd argument prefix len %d relayprefix len %d \n",
ip6rd->prefixlen,ip6rd->relay_prefixlen);
- return;
- }
-
- /*
- * Prepare The Tunnel configuration parameter to send to nss
- */
- memset(&tun6rdmsg, 0, sizeof(struct nss_tun6rd_msg));
- tun6rdcfg = &tun6rdmsg.msg.tun6rd_destroy;
-
- tun6rdcfg->prefix[0] = ntohl(ip6rd->prefix.s6_addr32[0]);
- tun6rdcfg->prefix[1] = ntohl(ip6rd->prefix.s6_addr32[1]);
- tun6rdcfg->prefix[2] = ntohl(ip6rd->prefix.s6_addr32[2]);
- tun6rdcfg->prefix[3] = ntohl(ip6rd->prefix.s6_addr32[3]);
-
- nss_tun6rd_trace(" Prefix %x:%x:%x:%x Prefix len %d \n",
- ip6rd->prefix.s6_addr32[0], ip6rd->prefix.s6_addr32[1],
- ip6rd->prefix.s6_addr32[2], ip6rd->prefix.s6_addr32[3],
- ip6rd->prefixlen);
-
- nss_tun6rd_trace("Sending Tunnle 6rd Down command %x \n",g_tun6rd.if_num);
-
- /*
- * Send 6rd Tunnel DESTROY command to NSS
- */
- nss_cmn_msg_init(&tun6rdmsg.cm, NSS_TUN6RD_INTERFACE, NSS_TUN6RD_TX_IF_DESTROY,
- sizeof(struct nss_tun6rd_destroy_msg), NULL, NULL);
-
- status = nss_tun6rd_tx(g_tun6rd.nss_ctx, &tun6rdmsg);
- if (status != NSS_TX_SUCCESS) {
- nss_tun6rd_error("Tunnel down command error %d \n", status);
- return;
+ return NOTIFY_BAD;
}
/*
* Un-Register 6rd tunnel with NSS
*/
- nss_unregister_tun6rd_if(g_tun6rd.if_num);
- g_tun6rd.nss_ctx = NULL;
- g_tun6rd.device_up = 0;
- return;
+ nss_unregister_tun6rd_if(if_number);
+ status = nss_dynamic_interface_dealloc_node(if_number, NSS_DYNAMIC_INTERFACE_TYPE_TUN6RD);
+ if (status != NSS_TX_SUCCESS) {
+ nss_tun6rd_warning("Dealloc node failure\n");
+ return NOTIFY_BAD;
+ }
+
+ return NOTIFY_DONE;
}
+
/*
* nss_tun6rd_dev_event()
* Net device notifier for 6rd module
@@ -324,23 +360,17 @@
{
struct net_device *netdev = (struct net_device *)dev;
- nss_tun6rd_trace("%s\n",__FUNCTION__);
switch (event) {
case NETDEV_UP:
- nss_tun6rd_trace(" NETDEV_UP :event %lu name %s \n",
- event,netdev->name);
- nss_tun6rd_dev_up(netdev);
- break;
+ nss_tun6rd_trace("NETDEV_UP: event %lu name %s\n", event, netdev->name);
+ return nss_tun6rd_dev_up(netdev);
case NETDEV_DOWN:
- nss_tun6rd_trace(" NETDEV_DOWN :event %lu name %s \n",
- event,netdev->name);
- nss_tun6rd_dev_down(netdev);
- break;
+ nss_tun6rd_trace("NETDEV_DOWN: event %lu name %s\n", event, netdev->name);
+ return nss_tun6rd_dev_down(netdev);
default:
- nss_tun6rd_trace("Unhandled notifier dev %s event %x \n",
- netdev->name,(int)event);
+ nss_tun6rd_trace("Unhandled notifier event %lu name %s\n",event, netdev->name);
break;
}
@@ -348,87 +378,12 @@
}
/*
- * nss_tun6rd_exception()
- * Exception handler registered to NSS driver
+ * Linux Net device Notifier
*/
-void nss_tun6rd_exception(void *ctx, void *buf, __attribute__((unused)) struct napi_struct *napi)
-{
- struct net_device *dev = (struct net_device *)ctx;
- struct sk_buff *skb = (struct sk_buff *)buf;
- const struct iphdr *iph;
+struct notifier_block nss_tun6rd_notifier = {
+ .notifier_call = nss_tun6rd_dev_event,
+};
- skb->dev = dev;
- nss_tun6rd_info("received - %d bytes name %s ver %x \n",
- skb->len,dev->name,skb->data[0]);
-
- iph = (const struct iphdr *)skb->data;
-
- /*
- * Packet after Decap/Encap Did not find the Rule.
- */
- if (iph->version == 4) {
- if(iph->protocol == IPPROTO_IPV6){
- skb_pull(skb, sizeof(struct iphdr));
- skb->protocol = htons(ETH_P_IPV6);
- skb_reset_network_header(skb);
- skb->pkt_type = PACKET_HOST;
- skb->ip_summed = CHECKSUM_NONE;
- dev_queue_xmit(skb);
- return;
- }
- skb->protocol = htons(ETH_P_IP);
- } else {
- 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_tun6rd_update_dev_stats
- * Update the Dev stats received from NetAp
- */
-static void nss_tun6rd_update_dev_stats(struct net_device *dev,
- struct nss_tun6rd_stats_sync_msg *sync_stats)
-{
- struct nss_tun6rd_stats stats;
- void *ptr;
-
- 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;
-
- ptr = (void *)&stats;
- ipip6_update_offload_stats(dev, ptr);
-}
-
-/**
- * @brief Event Callback to receive events from NSS
- * @param[in] pointer to net device context
- * @param[in] pointer to buffer
- * @return Returns void
- */
-void nss_tun6rd_event_receive(void *if_ctx, struct nss_tun6rd_msg *tnlmsg)
-{
- struct net_device *netdev = NULL;
- netdev = (struct net_device *)if_ctx;
-
- switch (tnlmsg->cm.type) {
- case NSS_TUN6RD_RX_STATS_SYNC:
- nss_tun6rd_update_dev_stats(netdev, (struct nss_tun6rd_stats_sync_msg *)&tnlmsg->msg.stats_sync);
- break;
-
- default:
- nss_tun6rd_info("%s: Unknown Event from NSS",
- __FUNCTION__);
- break;
- }
-}
/*
* nss_tun6rd_init_module()
@@ -442,11 +397,6 @@
register_netdevice_notifier(&nss_tun6rd_notifier);
nss_tun6rd_trace("Netdev Notifier registerd \n");
- g_tun6rd.if_num = NSS_TUN6RD_INTERFACE;
- g_tun6rd.netdev = NULL;
- g_tun6rd.device_up = 0;
- g_tun6rd.nss_ctx = NULL;
-
return 0;
}
@@ -456,7 +406,6 @@
*/
void __exit nss_tun6rd_exit_module(void)
{
-
unregister_netdevice_notifier(&nss_tun6rd_notifier);
nss_tun6rd_info("module unloaded\n");
}
diff --git a/nss_dynamic_interface.c b/nss_dynamic_interface.c
index 6b35852..ced3dea 100644
--- a/nss_dynamic_interface.c
+++ b/nss_dynamic_interface.c
@@ -336,5 +336,15 @@
di.current_if_num = -1;
}
+/*
+ * nss_is_dynamic_interface()
+ * Judge it is a valid dynamic interface
+ */
+bool nss_is_dynamic_interface(int if_num)
+{
+ return (if_num >= NSS_DYNAMIC_IF_START && if_num < NSS_SPECIAL_IF_START);
+}
+
EXPORT_SYMBOL(nss_dynamic_interface_alloc_node);
EXPORT_SYMBOL(nss_dynamic_interface_dealloc_node);
+EXPORT_SYMBOL(nss_is_dynamic_interface);
diff --git a/nss_hlos_if.h b/nss_hlos_if.h
index ec70158..1251ce8 100755
--- a/nss_hlos_if.h
+++ b/nss_hlos_if.h
@@ -22,6 +22,15 @@
#ifndef __NSS_HLOS_IF_H
#define __NSS_HLOS_IF_H
+#define MIN_NUM_CONN 256 /**< MIN Connection shared between IPv4 and IPv6 */
+#define MAX_TOTAL_NUM_CONN_IPV4_IPV6 8196 /**< MAX Connection shared between IPv4 and IPv6 */
+
+/*
+ * Variables used for sysctl updates.
+ */
+extern int nss_ipv4_conn_cfg;
+extern int nss_ipv6_conn_cfg;
+
/*
* Request/Response types
*/
diff --git a/nss_init.c b/nss_init.c
index 4d04bdd..1a6e56b 100755
--- a/nss_init.c
+++ b/nss_init.c
@@ -370,7 +370,6 @@
if (npd->tun6rd_enabled == NSS_FEATURE_ENABLED) {
nss_top->tun6rd_handler_id = nss_dev->id;
- nss_tun6rd_register_handler();
}
if (npd->tunipip6_enabled == NSS_FEATURE_ENABLED) {
@@ -829,30 +828,29 @@
.data = &nss_ctl_redirect,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec,
+ .proc_handler = proc_dointvec,
},
{
.procname = "debug",
.data = &nss_ctl_debug,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &nss_debug_handler,
+ .proc_handler = &nss_debug_handler,
},
{
.procname = "coredump",
.data = &nss_cmd_buf.coredump,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &nss_coredump_handler,
+ .proc_handler = &nss_coredump_handler,
},
{
.procname = "rps",
.data = &nss_rps_cfg,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &nss_rpscfg_handler,
+ .proc_handler = &nss_rpscfg_handler,
},
-
{ }
};
@@ -921,6 +919,12 @@
nss_dev_header = register_sysctl_table(nss_root);
/*
+ * Registering sysctl for ipv4/6 specific config.
+ */
+ nss_ipv4_register_sysctl();
+ nss_ipv6_register_sysctl();
+
+ /*
* Setup Runtime Sample values
*/
nss_runtime_samples.freq_scale[0].frequency = NSS_FREQ_110;
@@ -980,6 +984,12 @@
if (nss_dev_header)
unregister_sysctl_table(nss_dev_header);
+ /*
+ * Unregister ipv4/6 specific sysctl
+ */
+ nss_ipv4_unregister_sysctl();
+ nss_ipv6_unregister_sysctl();
+
platform_driver_unregister(&nss_driver);
}
diff --git a/nss_ipsec.c b/nss_ipsec.c
index e27535b..85ee3c0 100644
--- a/nss_ipsec.c
+++ b/nss_ipsec.c
@@ -229,6 +229,43 @@
EXPORT_SYMBOL(nss_ipsec_tx_msg);
/*
+ * nss_ipsec_tx_buf
+ * Send data packet for ipsec processing
+ */
+nss_tx_status_t nss_ipsec_tx_buf(struct sk_buff *os_buf, uint32_t if_num)
+{
+ int32_t status;
+ struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[nss_top_main.ipsec_handler_id];
+ uint16_t int_bit = nss_ctx->h2n_desc_rings[NSS_IF_DATA_QUEUE_0].desc_ring.int_bit;
+
+ nss_trace("%p: IPsec If Tx packet, id:%d, data=%p", nss_ctx, if_num, os_buf->data);
+
+ NSS_VERIFY_CTX_MAGIC(nss_ctx);
+ if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+ nss_warning("%p: 'IPsec If Tx' packet dropped as core not ready", nss_ctx);
+ return NSS_TX_FAILURE_NOT_READY;
+ }
+
+ status = nss_core_send_buffer(nss_ctx, if_num, os_buf, NSS_IF_DATA_QUEUE_0, H2N_BUFFER_PACKET, 0);
+ if (unlikely(status != NSS_CORE_STATUS_SUCCESS)) {
+ nss_warning("%p: Unable to enqueue 'IPsec If Tx' packet\n", nss_ctx);
+ if (status == NSS_CORE_STATUS_FAILURE_QUEUE) {
+ return NSS_TX_FAILURE_QUEUE;
+ }
+
+ return NSS_TX_FAILURE;
+ }
+
+ /*
+ * Kick the NSS awake so it can process our new entry.
+ */
+ nss_hal_send_interrupt(nss_ctx->nmap, int_bit, NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]);
+ return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_ipsec_tx_buf);
+
+/*
**********************************
Register APIs
**********************************
diff --git a/nss_ipsecmgr.c b/nss_ipsecmgr.c
index 6f486ec..3145789 100644
--- a/nss_ipsecmgr.c
+++ b/nss_ipsecmgr.c
@@ -28,7 +28,6 @@
#include <nss_ipsec.h>
#include "nss_ipsecmgr.h"
-
#if defined(CONFIG_DYNAMIC_DEBUG)
/*
* Compile messages for dynamic enable/disable
@@ -67,9 +66,9 @@
/* NSS IPsec entry state */
enum nss_ipsecmgr_entry_state {
- NSS_IPSECMGR_ENTRY_STATE_INIT = 0, /* init state of the entry */
- NSS_IPSECMGR_ENTRY_STATE_VALID = 1, /* entry is valid */
- NSS_IPSECMGR_ENTRY_STATE_INVALID = 2, /* entry is invalid */
+ NSS_IPSECMGR_ENTRY_STATE_INIT = 0, /* init state of the entry */
+ NSS_IPSECMGR_ENTRY_STATE_VALID = 1, /* entry is valid */
+ NSS_IPSECMGR_ENTRY_STATE_INVALID = 2, /* entry is invalid */
NSS_IPSECMGR_ENTRY_STATE_MAX
};
@@ -182,6 +181,7 @@
*/
data->cipher_algo = encap->cipher_algo;
data->esp_seq_skip = (encap->esp_seq_skip == 1);
+ data->esp_tail_skip = (encap->esp_tail_skip == 1);
data->esp_icv_len = encap->esp_icv_len;
data->auth_algo = encap->auth_algo;
@@ -216,11 +216,17 @@
data->cipher_algo = decap->cipher_algo;
data->esp_icv_len = decap->esp_icv_len;
+ data->esp_seq_skip = (decap->esp_seq_skip == 1);
+ data->esp_tail_skip = (decap->esp_tail_skip == 1);
data->auth_algo = decap->auth_algo;
data->crypto_index = decap->crypto_index;
data->nat_t_req = decap->nat_t_req;
+ if (data->nat_t_req) {
+ sel->dst_port = NSS_IPSECMGR_NATT_PORT_DATA;
+ }
+
data->window_size = decap->window_size;
}
@@ -713,11 +719,87 @@
*/
static netdev_tx_t nss_ipsecmgr_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
- nss_ipsecmgr_warn("tunnel transmit not implemented, freeing the skb\n");
+ uint32_t if_num;
+ struct iphdr *inner_ip;
+ struct nss_ipsecmgr_priv *priv;
+ struct nss_ipsecmgr_tbl *encap;
- dev_kfree_skb_any(skb);
+ if_num = NSS_IPSEC_ENCAP_IF_NUMBER;
+ priv = netdev_priv(dev);
+ encap = &priv->encap;
+
+ if (skb_is_nonlinear(skb)) {
+ nss_ipsecmgr_error("%p: NSS IPSEC does not support fragments %p\n", priv->nss_ctx, skb);
+ goto fail;
+ }
+
+ /*
+ * Check if skb is shared
+ */
+ if (unlikely(skb_shared(skb))) {
+ nss_ipsecmgr_error("%p: Shared skb is not supported: %p\n", priv->nss_ctx, skb);
+ goto fail;
+ }
+
+ /*
+ * Check the packet head room & tail room
+ */
+ if (unlikely(skb_headroom(skb) < dev->needed_headroom)) {
+ nss_ipsecmgr_error("%p: Insufficient head room :%d in skb: %p\n", priv->nss_ctx, skb_headroom(skb), skb);
+ goto fail;
+ }
+
+ if (unlikely(skb_tailroom(skb) < dev->needed_tailroom)) {
+ nss_ipsecmgr_error("%p: Insufficient tail room:%d in skb: %p\n", priv->nss_ctx, skb_tailroom(skb), skb);
+ goto fail;
+ }
+
+ /*
+ * Check if packet is given starting from network header
+ */
+ if (skb->data != skb_network_header(skb)) {
+ nss_ipsecmgr_error("%p: 'Skb data is not starting from IP header", priv->nss_ctx);
+ goto fail;
+ }
+
+ inner_ip = (struct iphdr *)ip_hdr(skb);
+
+ /*
+ * Validate if packet has ip options
+ */
+ if ((inner_ip->version != IPVERSION) || (inner_ip->ihl != 5)) {
+ nss_ipsecmgr_error("%p: Unsupported IP header ipver: 0x%x iphdr_len: 0x%x\n", priv->nss_ctx,
+ inner_ip->version, inner_ip->ihl);
+ goto fail;
+ }
+
+ /*
+ * Check the TTL value
+ */
+ if ((inner_ip->ttl == 0)) {
+ nss_ipsecmgr_error("%p: IP TTL is zero, unabled to transmit\n", priv->nss_ctx);
+ goto fail;
+ }
+
+ /*
+ * Send the packet down
+ */
+ if (nss_ipsec_tx_buf(skb, if_num) != 0) {
+ /*
+ * TODO: NEED TO STOP THE QUEUE
+ */
+ goto fail;
+ }
+
+ /*
+ * Increment the tx count
+ */
+ encap->total_tx++;
return NETDEV_TX_OK;
+
+fail:
+ return NETDEV_TX_BUSY;
}
/*
@@ -1001,7 +1083,6 @@
nss_ipsecmgr_error("Unknown rule type(%d) for Del operation\n", type);
return false;
}
-
return nss_ipsecmgr_op_send(dev, &nim, if_num, NSS_IPSEC_MSG_TYPE_DEL_RULE);
}
EXPORT_SYMBOL(nss_ipsecmgr_sa_del);
diff --git a/nss_ipv4.c b/nss_ipv4.c
index 05bdea3..68d28b9 100644
--- a/nss_ipv4.c
+++ b/nss_ipv4.c
@@ -18,6 +18,7 @@
* nss_ipv4.c
* NSS IPv4 APIs
*/
+#include <linux/sysctl.h>
#include <linux/ppp_channel.h>
#include "nss_tx_rx_common.h"
@@ -25,6 +26,8 @@
extern void nss_rx_metadata_ipv4_create_response(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim);
extern void nss_rx_ipv4_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync *nirs);
+int nss_ipv4_conn_cfg __read_mostly = 4096;
+
/*
* nss_ipv4_driver_conn_sync_update()
* Update driver specific information from the messsage.
@@ -300,7 +303,153 @@
}
}
+/*
+ * nss_ipv4_conn_cfg_callback()
+ * call back function for the ipv6 connection configuration handler
+ */
+static void nss_ipv4_conn_cfg_callback(void *app_data, struct nss_if_msg *nim)
+{
+
+ if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
+ nss_warning("IPv4 connection configuration failed with error: %d\n", nim->cm.error);
+ return;
+ }
+
+ nss_info("IPv4 connection configuration success: %d\n", nim->cm.error);
+}
+
+/*
+ * nss_ipv4_conn_cfg_handler()
+ * Sets the number of connections for IPv4
+ */
+static int nss_ipv4_conn_cfg_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ struct nss_top_instance *nss_top = &nss_top_main;
+ struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
+ struct nss_ipv4_msg nim;
+ struct nss_ipv4_rule_conn_cfg_msg *nirccm;
+ nss_tx_status_t nss_tx_status;
+ int ret = 1;
+ uint32_t sum_of_conn = nss_ipv4_conn_cfg + nss_ipv6_conn_cfg;
+
+ /*
+ * The input should be power of 2.
+ * Input for ipv4 and ipv6 sum togther should not exceed 8k
+ * Min. value should be at leat 256 connections. This is the
+ * minimum connections we will support for each of them.
+ */
+ if ((nss_ipv4_conn_cfg & (nss_ipv4_conn_cfg - 1)) ||
+ (sum_of_conn > MAX_TOTAL_NUM_CONN_IPV4_IPV6) ||
+ (nss_ipv4_conn_cfg < MIN_NUM_CONN)) {
+ nss_warning("%p: input supported connections (%d) does not adhere\
+ specifications\n1) not power of 2,\n2) is less than \
+ min val: %d, OR\n IPv4/6 total exceeds %d\n",
+ nss_ctx,
+ nss_ipv4_conn_cfg,
+ MIN_NUM_CONN,
+ MAX_TOTAL_NUM_CONN_IPV4_IPV6);
+ return ret;
+ }
+
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+
+ if (ret) {
+ return ret;
+ }
+
+ if ((!write)) {
+ nss_warning("%p: IPv4 supported connections write failed: %d\n", nss_ctx, nss_ipv4_conn_cfg);
+ return ret;
+ }
+
+
+ nss_info("%p: IPv4 supported connections: %d\n", nss_ctx, nss_ipv4_conn_cfg);
+
+ nss_cmn_msg_init(&nim.cm, NSS_IPV4_RX_INTERFACE, NSS_IPV4_TX_CONN_CFG_RULE_MSG,
+ sizeof(struct nss_ipv4_rule_conn_cfg_msg), nss_ipv4_conn_cfg_callback, NULL);
+
+ nirccm = &nim.msg.rule_conn_cfg;
+ nirccm->num_conn = htonl(nss_ipv4_conn_cfg);
+ nss_tx_status = nss_ipv4_tx(nss_ctx, &nim);
+
+ if (nss_tx_status != NSS_TX_SUCCESS) {
+ nss_warning("%p: nss_tx error setting IPv4 Connections: %d\n",
+ nss_ctx,
+ nss_ipv4_conn_cfg);
+ }
+ return ret;
+}
+
+static ctl_table nss_ipv4_table[] = {
+ {
+ .procname = "ipv4_conn",
+ .data = &nss_ipv4_conn_cfg,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_ipv4_conn_cfg_handler,
+ },
+ { }
+};
+
+static ctl_table nss_ipv4_dir[] = {
+ {
+ .procname = "ipv4cfg",
+ .mode = 0555,
+ .child = nss_ipv4_table,
+ },
+ { }
+};
+
+
+static ctl_table nss_ipv4_root_dir[] = {
+ {
+ .procname = "nss",
+ .mode = 0555,
+ .child = nss_ipv4_dir,
+ },
+ { }
+};
+
+static ctl_table nss_ipv4_root[] = {
+ {
+ .procname = "dev",
+ .mode = 0555,
+ .child = nss_ipv4_root_dir,
+ },
+ { }
+};
+
+static struct ctl_table_header *nss_ipv4_header;
+
+/*
+ * nss_ipv4_register_sysctl()
+ * Register sysctl specific to ipv4
+ */
+void nss_ipv4_register_sysctl(void)
+{
+ /*
+ * Register sysctl table.
+ */
+ nss_ipv4_header = register_sysctl_table(nss_ipv4_root);
+}
+
+/*
+ * nss_ipv4_unregister_sysctl()
+ * Unregister sysctl specific to ipv4
+ */
+void nss_ipv4_unregister_sysctl(void)
+{
+ /*
+ * Unregister sysctl table.
+ */
+ if (nss_ipv4_header) {
+ unregister_sysctl_table(nss_ipv4_header);
+ }
+}
+
EXPORT_SYMBOL(nss_ipv4_tx);
EXPORT_SYMBOL(nss_ipv4_notify_register);
EXPORT_SYMBOL(nss_ipv4_notify_unregister);
EXPORT_SYMBOL(nss_ipv4_get_mgr);
+EXPORT_SYMBOL(nss_ipv4_register_sysctl);
+EXPORT_SYMBOL(nss_ipv4_unregister_sysctl);
diff --git a/nss_ipv6.c b/nss_ipv6.c
index 94bfc81..3b51486 100644
--- a/nss_ipv6.c
+++ b/nss_ipv6.c
@@ -25,6 +25,8 @@
extern void nss_rx_metadata_ipv6_create_response(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_msg *nim);
extern void nss_rx_ipv6_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_conn_sync *nirs);
+int nss_ipv6_conn_cfg __read_mostly = 4096;
+
/*
* nss_ipv6_driver_conn_sync_update()
* Update driver specific information from the messsage.
@@ -300,8 +302,153 @@
}
}
+/*
+ * nss_ipv6_conn_cfg_callback()
+ * call back function for the ipv6 connection configuration handler
+ */
+static void nss_ipv6_conn_cfg_callback(void *app_data, struct nss_if_msg *nim)
+{
+ if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
+ nss_warning("IPv6 connection configuration failed with error: %d\n", nim->cm.error);
+ return;
+ }
+
+ nss_info("IPv6 connection configuration success: %d\n", nim->cm.error);
+}
+
+
+/*
+ * nss_ipv6_conn_cfg_handler()
+ * Sets the number of connections for IPv6
+ */
+static int nss_ipv6_conn_cfg_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ struct nss_top_instance *nss_top = &nss_top_main;
+ struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
+ struct nss_ipv6_msg nim;
+ struct nss_ipv6_rule_conn_cfg_msg *nirccm;
+ nss_tx_status_t nss_tx_status;
+ int ret = 1;
+ uint32_t sum_of_conn = nss_ipv4_conn_cfg + nss_ipv6_conn_cfg;
+
+ /*
+ * Specifications for input
+ * 1) The input should be power of 2.
+ * 2) Input for ipv4 and ipv6 sum togther should not exceed 8k
+ * 3) Min. value should be at leat 256 connections. This is the
+ * minimum connections we will support for each of them.
+ */
+ if ((nss_ipv6_conn_cfg & (nss_ipv6_conn_cfg - 1)) ||
+ (sum_of_conn > MAX_TOTAL_NUM_CONN_IPV4_IPV6) ||
+ (nss_ipv6_conn_cfg < MIN_NUM_CONN)) {
+ nss_warning("%p: input supported connections (%d) does not adhere\
+ specifications\n1) not power of 2,\n2) is less than \
+ min val: %d, OR\n IPv4/6 total exceeds %d\n",
+ nss_ctx,
+ nss_ipv6_conn_cfg,
+ MIN_NUM_CONN,
+ MAX_TOTAL_NUM_CONN_IPV4_IPV6);
+ return ret;
+ }
+
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+
+ if (ret) {
+ return ret;
+ }
+
+ if (!write) {
+ nss_warning("%p: IPv6 supported connections write failed: %d\n", nss_ctx, nss_ipv6_conn_cfg);
+ return ret;
+ }
+
+ nss_info("%p: IPv6 supported connections: %d\n", nss_ctx, nss_ipv6_conn_cfg);
+
+ nss_cmn_msg_init(&nim.cm, NSS_IPV6_RX_INTERFACE, NSS_IPV6_TX_CONN_CFG_RULE_MSG,
+ sizeof(struct nss_ipv6_rule_conn_cfg_msg), nss_ipv6_conn_cfg_callback, NULL);
+
+ nirccm = &nim.msg.rule_conn_cfg;
+ nirccm->num_conn = htonl(nss_ipv6_conn_cfg);
+ nss_tx_status = nss_ipv6_tx(nss_ctx, &nim);
+
+ if (nss_tx_status != NSS_TX_SUCCESS) {
+ nss_warning("%p: nss_tx error setting IPv6 Connections: %d\n",
+ nss_ctx,
+ nss_ipv6_conn_cfg);
+ }
+ return ret;
+}
+
+static ctl_table nss_ipv6_table[] = {
+ {
+ .procname = "ipv6_conn",
+ .data = &nss_ipv6_conn_cfg,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_ipv6_conn_cfg_handler,
+ },
+ { }
+};
+
+static ctl_table nss_ipv6_dir[] = {
+ {
+ .procname = "ipv6cfg",
+ .mode = 0555,
+ .child = nss_ipv6_table,
+ },
+ { }
+};
+
+static ctl_table nss_ipv6_root_dir[] = {
+ {
+ .procname = "nss",
+ .mode = 0555,
+ .child = nss_ipv6_dir,
+ },
+ { }
+};
+
+static ctl_table nss_ipv6_root[] = {
+ {
+ .procname = "dev",
+ .mode = 0555,
+ .child = nss_ipv6_root_dir,
+ },
+ { }
+};
+
+static struct ctl_table_header *nss_ipv6_header;
+
+/*
+ * nss_ipv6_register_sysctl()
+ * Register sysctl specific to ipv4
+ */
+void nss_ipv6_register_sysctl(void)
+{
+ /*
+ * Register sysctl table.
+ */
+ nss_ipv6_header = register_sysctl_table(nss_ipv6_root);
+}
+
+/*
+ * nss_ipv6_unregister_sysctl()
+ * Unregister sysctl specific to ipv4
+ */
+void nss_ipv6_unregister_sysctl(void)
+{
+ /*
+ * Unregister sysctl table.
+ */
+ if (nss_ipv6_header) {
+ unregister_sysctl_table(nss_ipv6_header);
+ }
+}
+
EXPORT_SYMBOL(nss_ipv6_tx);
EXPORT_SYMBOL(nss_ipv6_notify_register);
EXPORT_SYMBOL(nss_ipv6_notify_unregister);
EXPORT_SYMBOL(nss_ipv6_get_mgr);
EXPORT_SYMBOL(nss_ipv6_register_handler);
+EXPORT_SYMBOL(nss_ipv6_register_sysctl);
+EXPORT_SYMBOL(nss_ipv6_unregister_sysctl);
diff --git a/nss_qdisc/Makefile b/nss_qdisc/Makefile
index 4051a0e..ec25d0d 100755
--- a/nss_qdisc/Makefile
+++ b/nss_qdisc/Makefile
@@ -22,4 +22,5 @@
nss_prio.o \
nss_bf.o \
nss_wrr.o \
- nss_htb.o
+ nss_htb.o \
+ nss_blackhole.o
diff --git a/nss_qdisc/nss_blackhole.c b/nss_qdisc/nss_blackhole.c
new file mode 100644
index 0000000..6a4e753
--- /dev/null
+++ b/nss_qdisc/nss_blackhole.c
@@ -0,0 +1,253 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2014, 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 "nss_qdisc.h"
+
+/*
+ * nss_blackhole private qdisc structure
+ */
+struct nss_blackhole_sched_data {
+ struct nss_qdisc nq; /* Common base class for all nss qdiscs */
+ u8 set_default; /* Flag to set qdisc as default qdisc for enqueue */
+};
+
+/*
+ * nss_blackhole_enqueue()
+ * Enqueue API for nss blackhole qdisc.
+ */
+static int nss_blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ return nss_qdisc_enqueue(skb, sch);
+}
+
+/*
+ * nss_blackhole_dequeue()
+ * Dequeue API for nss blackhole qdisc.
+ */
+static struct sk_buff *nss_blackhole_dequeue(struct Qdisc *sch)
+{
+ return nss_qdisc_dequeue(sch);
+}
+
+/*
+ * nss_blackhole_drop()
+ * The following function drops a packet from HLOS queue.
+ *
+ * Note, this does not drop packets from queues in the NSS. We do not support that.
+ */
+static unsigned int nss_blackhole_drop(struct Qdisc *sch)
+{
+ nss_qdisc_info("%s: qdisc %x dropping\n", __func__, sch->handle);
+ return nss_qdisc_drop(sch);
+}
+
+/*
+ * nss_blackhole_reset()
+ * Resets the nss blackhole qdisc.
+ */
+static void nss_blackhole_reset(struct Qdisc *sch)
+{
+ nss_qdisc_info("%s: qdisc %x resetting\n", __func__, sch->handle);
+ nss_qdisc_reset(sch);
+}
+
+/*
+ * nss_blackhole_destroy()
+ * Destroys the nss blackhole qdisc.
+ */
+static void nss_blackhole_destroy(struct Qdisc *sch)
+{
+ 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("%s: destroying qdisc %x\n", __func__, sch->handle);
+ nss_qdisc_destroy(nq);
+}
+
+/*
+ * nss_blackhole policy structure
+ */
+static const struct nla_policy nss_blackhole_policy[TCA_NSSBLACKHOLE_MAX + 1] = {
+ [TCA_NSSBLACKHOLE_PARMS] = { .len = sizeof(struct tc_nssblackhole_qopt) },
+};
+
+/*
+ * nss_blackhole_change()
+ * Function call used to configure the parameters of the nss blackhole qdisc.
+ */
+static int nss_blackhole_change(struct Qdisc *sch, struct nlattr *opt)
+{
+ struct nss_blackhole_sched_data *q;
+ struct nlattr *na[TCA_NSSBLACKHOLE_MAX + 1];
+ struct tc_nssblackhole_qopt *qopt;
+ int err;
+ struct nss_if_msg nim;
+
+ q = qdisc_priv(sch);
+
+ if (opt == NULL) {
+ return -EINVAL;
+ }
+
+ err = nla_parse_nested(na, TCA_NSSBLACKHOLE_MAX, opt, nss_blackhole_policy);
+ if (err < 0)
+ return err;
+
+ if (na[TCA_NSSBLACKHOLE_PARMS] == NULL)
+ return -EINVAL;
+
+ qopt = nla_data(na[TCA_NSSBLACKHOLE_PARMS]);
+
+ /*
+ * Required for basic stats display
+ */
+ sch->limit = 0;
+
+ q->set_default = qopt->set_default;
+ nss_qdisc_info("%s: qdisc set_default = %u\n", __func__, qopt->set_default);
+
+ /*
+ * Underneath nss_bloackhole uses a fifo in the NSS. This is why we are sending down a configuration
+ * message to a fifo node. There are no blackhole shaper in the NSS as yet.
+ *
+ * Note: We simply set the limit of fifo to zero to get the blackhole behavior.
+ */
+ nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
+ nim.msg.shaper_configure.config.msg.shaper_node_config.snc.fifo_param.limit = 0;
+ nim.msg.shaper_configure.config.msg.shaper_node_config.snc.fifo_param.drop_mode = NSS_SHAPER_FIFO_DROP_MODE_TAIL;
+ if (nss_qdisc_configure(&q->nq, &nim, NSS_SHAPER_CONFIG_TYPE_FIFO_CHANGE_PARAM) < 0) {
+ nss_qdisc_error("%s: qdisc %x configuration failed\n", __func__, sch->handle);
+ return -EINVAL;
+ }
+
+ /*
+ * There is nothing we need to do if the qdisc is not
+ * set as default qdisc.
+ */
+ if (q->set_default == 0)
+ return 0;
+
+ /*
+ * Set this qdisc to be the default qdisc for enqueuing packets.
+ */
+ if (nss_qdisc_set_default(&q->nq) < 0) {
+ nss_qdisc_error("%s: qdisc %x set_default failed\n", __func__, sch->handle);
+ return -EINVAL;
+ }
+
+ nss_qdisc_info("%s: qdisc %x set as default\n", __func__, q->nq.qos_tag);
+ return 0;
+}
+
+/*
+ * nss_blackhole_init()
+ * Initializes a nss blackhole qdisc.
+ */
+static int nss_blackhole_init(struct Qdisc *sch, struct nlattr *opt)
+{
+ struct nss_qdisc *nq = qdisc_priv(sch);
+
+ if (opt == NULL)
+ return -EINVAL;
+
+ nss_qdisc_info("%s: qdisc %x initializing\n", __func__, sch->handle);
+ nss_blackhole_reset(sch);
+
+ if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0) < 0)
+ return -EINVAL;
+
+ nss_qdisc_info("%s: qdisc %x initialized with parent %x\n", __func__, sch->handle, sch->parent);
+ if (nss_blackhole_change(sch, opt) < 0) {
+ nss_qdisc_destroy(nq);
+ return -EINVAL;
+ }
+
+ /*
+ * Start the stats polling timer
+ */
+ nss_qdisc_start_basic_stats_polling(nq);
+
+ return 0;
+}
+
+/*
+ * nss_blackhole_dump()
+ * Dumps qdisc parameters for nss blackhole.
+ */
+static int nss_blackhole_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+ struct nss_blackhole_sched_data *q;
+ struct nlattr *opts = NULL;
+ struct tc_nssblackhole_qopt opt;
+
+ nss_qdisc_info("%s: qdisc %x dumping!\n", __func__, sch->handle);
+
+ q = qdisc_priv(sch);
+ if (q == NULL) {
+ return -1;
+ }
+
+ opt.set_default = q->set_default;
+
+ opts = nla_nest_start(skb, TCA_OPTIONS);
+ if (opts == NULL) {
+ goto nla_put_failure;
+ }
+ if (nla_put(skb, TCA_NSSBLACKHOLE_PARMS, sizeof(opt), &opt))
+ goto nla_put_failure;
+
+ return nla_nest_end(skb, opts);
+
+nla_put_failure:
+ nla_nest_cancel(skb, opts);
+ return -EMSGSIZE;
+}
+
+/*
+ * nss_blackhole_peek()
+ * Peeks the first packet in queue for this qdisc.
+ *
+ * Note: This just peeks at the first packet in what is present in HLOS. This does not
+ * perform an actual peak into the queue in the NSS. Given the async delay between
+ * the processors, there is less use in implementing this function.
+ */
+static struct sk_buff *nss_blackhole_peek(struct Qdisc *sch)
+{
+ nss_qdisc_info("%s: qdisc %x peeked\n", __func__, sch->handle);
+ return nss_qdisc_peek(sch);
+}
+
+/*
+ * Registration structure for nss blackhole qdisc
+ */
+struct Qdisc_ops nss_blackhole_qdisc_ops __read_mostly = {
+ .id = "nssblackhole",
+ .priv_size = sizeof(struct nss_blackhole_sched_data),
+ .enqueue = nss_blackhole_enqueue,
+ .dequeue = nss_blackhole_dequeue,
+ .peek = nss_blackhole_peek,
+ .drop = nss_blackhole_drop,
+ .init = nss_blackhole_init,
+ .reset = nss_blackhole_reset,
+ .destroy = nss_blackhole_destroy,
+ .change = nss_blackhole_change,
+ .dump = nss_blackhole_dump,
+ .owner = THIS_MODULE,
+};
diff --git a/nss_qdisc/nss_blackhole.h b/nss_qdisc/nss_blackhole.h
new file mode 100644
index 0000000..58dce8b
--- /dev/null
+++ b/nss_qdisc/nss_blackhole.h
@@ -0,0 +1,17 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2014, 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.
+ **************************************************************************
+ */
+
+extern struct Qdisc_ops nss_blackhole_qdisc_ops;
diff --git a/nss_qdisc/nss_fifo.c b/nss_qdisc/nss_fifo.c
index 4b873c4..7f4ab45 100644
--- a/nss_qdisc/nss_fifo.c
+++ b/nss_qdisc/nss_fifo.c
@@ -177,7 +177,7 @@
return nla_nest_end(skb, opts);
-nla_put_failure:
+nla_put_failure:
nla_nest_cancel(skb, opts);
return -EMSGSIZE;
}
diff --git a/nss_qdisc/nss_qdisc.c b/nss_qdisc/nss_qdisc.c
index 84bea64..7eaff17 100644
--- a/nss_qdisc/nss_qdisc.c
+++ b/nss_qdisc/nss_qdisc.c
@@ -24,6 +24,7 @@
#include "nss_wrr.h"
#include "nss_wfq.h"
#include "nss_htb.h"
+#include "nss_blackhole.h"
void *nss_qdisc_ctx; /* Shaping context for nss_qdisc */
wait_queue_head_t nss_qdics_wq; /* Wait queue used to wait on responses from the NSS */
@@ -1014,7 +1015,11 @@
INIT_HLIST_NODE(&nq->hnode);
hash = nss_qdisc_gen_hash(nq->qos_tag);
+
+ spin_lock_bh(&nq_root->lock);
hlist_add_head(&nq->hnode, &nq_root->hash[hash]);
+ spin_unlock_bh(&nq_root->lock);
+
nss_qdisc_trace("%s: added qdisc %x to root %x's hash at index %u\n",
__func__, nq->qos_tag, nq_root->qos_tag, hash);
}
@@ -1023,10 +1028,17 @@
* nss_qdisc_root_hash_remove()
* Removes nss qdisc from root hash.
*/
-static inline void nss_qdisc_root_hash_remove(struct nss_qdisc *nq)
+static inline void nss_qdisc_root_hash_remove(struct nss_qdisc *nq_root, struct nss_qdisc *nq)
{
nss_qdisc_trace("%s: deleting qdisc %x from root hash\n", __func__, nq->qos_tag);
+
+ /*
+ * We need to hold the root lock since that is the node
+ * that maintains the hash list.
+ */
+ spin_lock_bh(&nq_root->lock);
hlist_del(&nq->hnode);
+ spin_unlock_bh(&nq_root->lock);
}
/*
@@ -1051,6 +1063,7 @@
/*
* Parse through the list to find a match.
*/
+ spin_lock_bh(&nq_root->lock);
hlist_for_each_entry(nq, n, &nq_root->hash[hash], hnode) {
/*
@@ -1069,17 +1082,23 @@
* more likely that we find our match at the head.
*/
if (likely(head)) {
+ spin_unlock_bh(&nq_root->lock);
return nq;
}
/*
* If the match was not at the head, we detach and attach it
- * back at the front/head.
+ * back at the front/head. These helper functions need to be
+ * called outside the lock.
*/
- nss_qdisc_root_hash_remove(nq);
+ spin_unlock_bh(&nq_root->lock);
+ nss_qdisc_root_hash_remove(nq_root, nq);
nss_qdisc_root_hash_insert(nq_root, nq);
+
return nq;
}
+
+ spin_unlock_bh(&nq_root->lock);
return NULL;
}
@@ -1681,14 +1700,15 @@
}
/*
+ * Free allocated hash table at root
+ */
+ nss_qdisc_root_hash_free(nq);
+
+ /*
* Begin by freeing the root shaper node
*/
nss_qdisc_root_cleanup_free_node(nq);
- /*
- * Free allocated hash table at root
- */
- nss_qdisc_root_hash_free(nq);
} else {
/*
* Begin by removing ourselves from the root hash.
@@ -1696,10 +1716,7 @@
*/
struct Qdisc *root = qdisc_root(nq->qdisc);
struct nss_qdisc *nq_root = qdisc_priv(root);
- spin_lock_bh(&nq_root->lock);
- nss_qdisc_root_hash_remove(nq);
- spin_unlock_bh(&nq_root->lock);
-
+ nss_qdisc_root_hash_remove(nq_root, nq);
nss_qdisc_child_cleanup_free_node(nq);
}
@@ -1737,6 +1754,12 @@
int msg_type;
/*
+ * Initialize locks
+ */
+ spin_lock_init(&nq->bounce_protection_lock);
+ spin_lock_init(&nq->lock);
+
+ /*
* Record our qdisc and type in the private region for handy use
*/
nq->qdisc = sch;
@@ -2385,6 +2408,11 @@
return ret;
nss_qdisc_info("nsshtb registered");
+ ret = register_qdisc(&nss_blackhole_qdisc_ops);
+ if (ret != 0)
+ return ret;
+ nss_qdisc_info("nssblackhole registered");
+
ret = register_netdevice_notifier(&nss_qdisc_device_notifier);
if (ret != 0)
return ret;
@@ -2422,6 +2450,9 @@
unregister_qdisc(&nss_htb_qdisc_ops);
nss_qdisc_info("nsshtb unregistered\n");
+ unregister_qdisc(&nss_blackhole_qdisc_ops);
+ nss_qdisc_info("nssblackhole unregistered\n");
+
unregister_netdevice_notifier(&nss_qdisc_device_notifier);
}
diff --git a/nss_tun6rd.c b/nss_tun6rd.c
index b4d83d0..705f041 100644
--- a/nss_tun6rd.c
+++ b/nss_tun6rd.c
@@ -24,9 +24,11 @@
{
struct nss_tun6rd_msg *ntm = (struct nss_tun6rd_msg *)ncm;
void *ctx;
+
nss_tun6rd_msg_callback_t cb;
- BUG_ON(ncm->interface != NSS_TUN6RD_INTERFACE);
+ BUG_ON(!nss_is_dynamic_interface(ncm->interface));
+
/*
* Is this a valid request/response packet?
*/
@@ -77,7 +79,6 @@
cb(ctx, ntm);
}
-
/*
* nss_tun6rd_tx()
* Transmit a tun6rd message to NSSFW
@@ -98,7 +99,7 @@
/*
* Sanity check the message
*/
- if (ncm->interface != NSS_TUN6RD_INTERFACE) {
+ if (!nss_is_dynamic_interface(ncm->interface)) {
nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
return NSS_TX_FAILURE;
}
@@ -151,17 +152,26 @@
/*
* nss_register_tun6rd_if()
*/
-struct nss_ctx_instance *nss_register_tun6rd_if(uint32_t if_num,
- nss_tun6rd_callback_t tun6rd_callback,
- nss_tun6rd_msg_callback_t event_callback, struct net_device *netdev)
+struct nss_ctx_instance *nss_register_tun6rd_if(uint32_t if_num, nss_tun6rd_callback_t tun6rd_callback,
+ nss_tun6rd_msg_callback_t event_callback, struct net_device *netdev)
{
- nss_assert((if_num >= NSS_MAX_VIRTUAL_INTERFACES) && (if_num < NSS_MAX_NET_INTERFACES));
+ nss_assert((if_num >= NSS_DYNAMIC_IF_START) && (if_num < NSS_SPECIAL_IF_START));
- nss_top_main.if_ctx[if_num] = netdev;
- nss_top_main.if_rx_callback[if_num] = tun6rd_callback;
- nss_top_main.tun6rd_msg_callback = event_callback;
+ nss_top_main.if_ctx[if_num] = netdev;
+ nss_top_main.if_rx_callback[if_num] = tun6rd_callback;
+ nss_top_main.tun6rd_msg_callback = event_callback;
- return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.tun6rd_handler_id];
+ nss_core_register_handler(if_num, nss_tun6rd_handler, NULL);
+
+ return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.tun6rd_handler_id];
+}
+
+/*
+ * nss_get_tun6rd_context()
+ */
+struct nss_ctx_instance * nss_tun6rd_get_context()
+{
+ return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.tun6rd_handler_id];
}
/*
@@ -169,22 +179,16 @@
*/
void nss_unregister_tun6rd_if(uint32_t if_num)
{
- nss_assert((if_num >= NSS_MAX_VIRTUAL_INTERFACES) && (if_num < NSS_MAX_NET_INTERFACES));
+ nss_assert(nss_is_dynamic_interface(ncm->interface));
- nss_top_main.if_rx_callback[if_num] = NULL;
- nss_top_main.if_ctx[if_num] = NULL;
- nss_top_main.tun6rd_msg_callback = NULL;
+ nss_top_main.if_rx_callback[if_num] = NULL;
+ nss_top_main.if_ctx[if_num] = NULL;
+ nss_top_main.tun6rd_msg_callback = NULL;
+
+ nss_core_unregister_handler(if_num);
}
-/*
- * nss_tun6rd_register_handler()
- */
-void nss_tun6rd_register_handler()
-{
- nss_core_register_handler(NSS_TUN6RD_INTERFACE, nss_tun6rd_handler, NULL);
-}
-
-
+EXPORT_SYMBOL(nss_tun6rd_get_context);
EXPORT_SYMBOL(nss_tun6rd_tx);
EXPORT_SYMBOL(nss_register_tun6rd_if);
EXPORT_SYMBOL(nss_unregister_tun6rd_if);
diff --git a/nss_tx_rx_common.h b/nss_tx_rx_common.h
index 9d155bd..9e29a30 100644
--- a/nss_tx_rx_common.h
+++ b/nss_tx_rx_common.h
@@ -69,7 +69,6 @@
extern void nss_ipv4_register_handler(void);
extern void nss_ipv6_register_handler(void);
extern void nss_n2h_register_handler(void);
-extern void nss_tun6rd_register_handler(void);
extern void nss_tunipip6_register_handler(void);
extern void nss_pppoe_register_handler(void);
extern void nss_core_freq_register_handler(void);