Merge "[qca-nss-drv]: Add Jumbo frame support"
diff --git a/nss_connmgr_ipv4.c b/nss_connmgr_ipv4.c
index 853fc6a..5dcb828 100755
--- a/nss_connmgr_ipv4.c
+++ b/nss_connmgr_ipv4.c
@@ -114,7 +114,7 @@
typedef uint8_t mac_addr_t[6];
typedef uint32_t ipv4_addr_t;
-#define is_bridge_port(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
+#define is_bridge_port(dev) (dev && (dev->priv_flags & IFF_BRIDGE_PORT))
#define is_bridge_device(dev) (dev->priv_flags & IFF_EBRIDGE)
#define is_lag_master(dev) ((dev->flags & IFF_MASTER) \
&& (dev->priv_flags & IFF_BONDING))
@@ -556,6 +556,14 @@
nss_tx_status_t nss_tx_status;
/*
+ * Only process IPV4 packets in bridge hook
+ */
+ if(skb->protocol != htons(ETH_P_IP)){
+ NSS_CONNMGR_DEBUG_TRACE("non ipv4 , ignoring: %p\n", skb);
+ return NF_ACCEPT;
+ }
+
+ /*
* Don't process broadcast or multicast
*/
if (skb->pkt_type == PACKET_BROADCAST) {
@@ -604,6 +612,17 @@
}
NSS_CONNMGR_DEBUG_TRACE("skb: %p tracked by connection: %p\n", skb, ct);
+
+ /*
+ * Ignore packets that are related to a valid connection, such as ICMP destination
+ * unreachable error packets
+ */
+ if ((ctinfo == IP_CT_RELATED) || (ctinfo == IP_CT_RELATED_REPLY)) {
+ dev_put(in);
+ NSS_CONNMGR_DEBUG_TRACE("skb: Related packet %p tracked by connection: %p\n", skb, ct);
+ return NF_ACCEPT;
+ }
+
/*
* Special untracked connection is not monitored
*/
@@ -633,11 +652,16 @@
/*
* If destination is not reachable, ignore.
*/
- if (skb_mac_header_was_set(skb)
- && br_port_dev_get(out->master, eth_hdr(skb)->h_dest) == NULL) {
- dev_put(in);
- NSS_CONNMGR_DEBUG_TRACE("Dest not reachable, skb(%p)\n", skb);
- return NF_ACCEPT;
+ if (skb_mac_header_was_set(skb)) {
+ struct net_device *dest_dev = br_port_dev_get(out->master, eth_hdr(skb)->h_dest);
+
+ if (dest_dev == NULL) {
+ dev_put(in);
+ NSS_CONNMGR_DEBUG_TRACE("Dest not reachable, skb(%p)\n", skb);
+ return NF_ACCEPT;
+ } else {
+ dev_put(dest_dev);
+ }
}
/*
@@ -803,11 +827,17 @@
* Configure the MAC addresses for the flow
*/
eh = (struct ethhdr *)skb->mac_header;
-
- memcpy(unic.src_mac, eh->h_source, ETH_HLEN);
- memcpy(unic.src_mac_xlate, eh->h_source, ETH_HLEN);
- memcpy(unic.dest_mac, eh->h_dest, ETH_HLEN);
- memcpy(unic.dest_mac_xlate, eh->h_dest, ETH_HLEN);
+ if (ctinfo < IP_CT_IS_REPLY) {
+ memcpy(unic.src_mac, eh->h_source, ETH_HLEN);
+ memcpy(unic.dest_mac, eh->h_dest, ETH_HLEN);
+ memcpy(unic.src_mac_xlate, eh->h_source, ETH_HLEN);
+ memcpy(unic.dest_mac_xlate, eh->h_dest, ETH_HLEN);
+ } else {
+ memcpy(unic.src_mac, eh->h_dest, ETH_HLEN);
+ memcpy(unic.dest_mac, eh->h_source, ETH_HLEN);
+ memcpy(unic.src_mac_xlate, eh->h_dest, ETH_HLEN);
+ memcpy(unic.dest_mac_xlate, eh->h_source, ETH_HLEN);
+ }
} else {
/*
* This is a routed + bridged flow
@@ -1436,6 +1466,15 @@
NSS_CONNMGR_DEBUG_TRACE("skb: %p tracked by connection: %p\n", skb, ct);
/*
+ * Ignore packets that are related to a valid connection, such as ICMP destination
+ * unreachable error packets
+ */
+ if ((ctinfo == IP_CT_RELATED) || (ctinfo == IP_CT_RELATED_REPLY)) {
+ NSS_CONNMGR_DEBUG_TRACE("skb: Related packet %p tracked by connection: %p\n", skb, ct);
+ goto out;
+ }
+
+ /*
* Special untracked connection is not monitored
*/
if (ct == &nf_conntrack_untracked) {
@@ -2047,48 +2086,65 @@
struct rtnl_link_stats64 stats;
indev = nss_get_interface_dev(nss_connmgr_ipv4.nss_context, connection->src_interface);
+ if (indev == NULL) {
+ /*
+ * Possible sync for a deleted interface
+ */
+ return;
+ }
if (is_lag_slave(indev)) {
- if (indev->master) {
- indev = indev->master;
- } else {
+ if (indev->master == NULL) {
+ NSS_CONNMGR_DEBUG_TRACE("Could not find master for LAG slave %s\n", indev->name);
return;
}
+ indev = indev->master;
} else if (connection->ingress_vlan_tag != NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED) {
indev = __vlan_find_dev_deep(indev, connection->ingress_vlan_tag);
+ if (indev == NULL) {
+ /*
+ * Possible sync for a deleted VLAN interface
+ */
+ return;
+ }
}
outdev = nss_get_interface_dev(nss_connmgr_ipv4.nss_context, connection->dest_interface);
- if (is_lag_slave(outdev)) {
- if (outdev->master) {
- outdev = outdev->master;
- } else {
- return;
- }
- } else if (connection->egress_vlan_tag != NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED) {
- outdev = __vlan_find_dev_deep(outdev, connection->egress_vlan_tag);
+ if (outdev == NULL) {
+ /*
+ * Possible sync for a deleted interface
+ */
+ return;
}
- /*
- * Check if we have a bridge to update
- */
- if (!is_bridge_port(indev) && !is_bridge_port(outdev))
- return;
+ if (is_lag_slave(outdev)) {
+ if (outdev->master == NULL) {
+ NSS_CONNMGR_DEBUG_TRACE("Could not find master for LAG slave %s\n", outdev->name);
+ return;
+ }
+ outdev = outdev->master;
+ } else if (connection->egress_vlan_tag != NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED) {
+ outdev = __vlan_find_dev_deep(outdev, connection->egress_vlan_tag);
+ if (outdev == NULL) {
+ /*
+ * Possible sync for a deleted VLAN interface
+ */
+ return;
+ }
+ }
- /*
- * Update bridge device statistics for routing flows that have
- * a bridge in the path. We should avoid updating bridge device
- * for flows that are forwrded within the bridge.
- */
if (is_bridge_port(indev))
{
/*
* Refresh bridge MAC table if necessary
*/
- if (!final_sync) {
+ if (!final_sync && sync->flow_rx_packet_count) {
br_refresh_fdb_entry(indev, connection->src_mac_addr);
}
+ /*
+ * Update bridge interface stats for L3 flows involving a bridge
+ */
if (indev->master != outdev->master) {
stats.rx_packets = sync->flow_rx_packet_count;
stats.rx_bytes = sync->flow_rx_byte_count;
@@ -2103,10 +2159,13 @@
/*
* Refresh bridge MAC table if necessary
*/
- if (!final_sync) {
+ if (!final_sync && sync->return_rx_packet_count) {
br_refresh_fdb_entry(outdev, connection->dest_mac_addr);
}
+ /*
+ * Update bridge interface stats for L3 flows involving a bridge
+ */
if (indev->master != outdev->master) {
stats.rx_packets = sync->return_rx_packet_count;
stats.rx_bytes = sync->return_rx_byte_count;
diff --git a/nss_connmgr_ipv6.c b/nss_connmgr_ipv6.c
index 9519f71..8f62f86 100755
--- a/nss_connmgr_ipv6.c
+++ b/nss_connmgr_ipv6.c
@@ -159,7 +159,7 @@
typedef uint8_t mac_addr_t[6];
typedef uint32_t ipv6_addr_t[4];
-#define is_bridge_port(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
+#define is_bridge_port(dev) (dev && (dev->priv_flags & IFF_BRIDGE_PORT))
#define is_bridge_device(dev) (dev->priv_flags & IFF_EBRIDGE)
#define is_lag_master(dev) ((dev->flags & IFF_MASTER) \
&& (dev->priv_flags & IFF_BONDING))
@@ -815,6 +815,14 @@
nss_tx_status_t nss_tx_status;
/*
+ * Only process IPV6 packets in bridge hook
+ */
+ if(skb->protocol != htons(ETH_P_IPV6)){
+ NSS_CONNMGR_DEBUG_TRACE("non ipv6 , ignoring: %p\n", skb);
+ return NF_ACCEPT;
+ }
+
+ /*
* Don't process broadcast or multicast
*/
if (skb->pkt_type == PACKET_BROADCAST) {
@@ -864,6 +872,16 @@
NSS_CONNMGR_DEBUG_TRACE("skb: %p tracked by connection: %p\n", skb, ct);
/*
+ * Ignore packets that are related to a valid connection, such as ICMP destination
+ * unreachable error packets
+ */
+ if ((ctinfo == IP_CT_RELATED) || (ctinfo == IP_CT_RELATED_REPLY)) {
+ dev_put(in);
+ NSS_CONNMGR_DEBUG_TRACE("skb: Related packet %p tracked by connection: %p\n", skb, ct);
+ return NF_ACCEPT;
+ }
+
+ /*
* Special untracked connection is not monitored
*/
if (ct == &nf_conntrack_untracked) {
@@ -892,11 +910,16 @@
/*
* If destination is not reachable, ignore.
*/
- if (skb_mac_header_was_set(skb)
- && br_port_dev_get(out->master, eth_hdr(skb)->h_dest) == NULL) {
- dev_put(in);
- NSS_CONNMGR_DEBUG_TRACE("Dest not reachable, skb(%p)\n", skb);
- return NF_ACCEPT;
+ if (skb_mac_header_was_set(skb)) {
+ struct net_device *dest_dev = br_port_dev_get(out->master, eth_hdr(skb)->h_dest);
+
+ if (dest_dev == NULL) {
+ dev_put(in);
+ NSS_CONNMGR_DEBUG_TRACE("Dest not reachable, skb(%p)\n", skb);
+ return NF_ACCEPT;
+ } else {
+ dev_put(dest_dev);
+ }
}
/*
@@ -1044,9 +1067,13 @@
* Configure the MAC addresses for the flow
*/
eh = (struct ethhdr *)skb->mac_header;
-
- memcpy(unic.src_mac, eh->h_source, ETH_HLEN);
- memcpy(unic.dest_mac, eh->h_dest, ETH_HLEN);
+ if (ctinfo < IP_CT_IS_REPLY) {
+ memcpy(unic.src_mac, eh->h_source, ETH_HLEN);
+ memcpy(unic.dest_mac, eh->h_dest, ETH_HLEN);
+ } else {
+ memcpy(unic.src_mac, eh->h_dest, ETH_HLEN);
+ memcpy(unic.dest_mac, eh->h_source, ETH_HLEN);
+ }
} else {
/*
* This is a routed + bridged flow
@@ -1436,6 +1463,15 @@
NSS_CONNMGR_DEBUG_TRACE("skb: %p tracked by connection: %p\n", skb, ct);
/*
+ * Ignore packets that are related to a valid connection, such as ICMP destination
+ * unreachable error packets
+ */
+ if ((ctinfo == IP_CT_RELATED) || (ctinfo == IP_CT_RELATED_REPLY)) {
+ NSS_CONNMGR_DEBUG_TRACE("skb: Related packet %p tracked by connection: %p\n", skb, ct);
+ goto out;
+ }
+
+ /*
* Special untracked connection is not monitored
*/
if (ct == &nf_conntrack_untracked) {
@@ -1986,48 +2022,65 @@
struct rtnl_link_stats64 stats;
indev = nss_get_interface_dev(nss_connmgr_ipv6.nss_context, connection->src_interface);
+ if (indev == NULL) {
+ /*
+ * Possible sync for a deleted interface
+ */
+ return;
+ }
if (is_lag_slave(indev)) {
- if (indev->master) {
- indev = indev->master;
- } else {
+ if (indev->master == NULL) {
+ NSS_CONNMGR_DEBUG_TRACE("Could not find master for LAG slave %s\n", indev->name);
return;
}
+ indev = indev->master;
} else if (connection->ingress_vlan_tag != NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED) {
indev = __vlan_find_dev_deep(indev, connection->ingress_vlan_tag);
+ if (indev == NULL) {
+ /*
+ * Possible sync for a deleted VLAN interface
+ */
+ return;
+ }
}
outdev = nss_get_interface_dev(nss_connmgr_ipv6.nss_context, connection->dest_interface);
- if (is_lag_slave(outdev)) {
- if (outdev->master) {
- outdev = outdev->master;
- } else {
- return;
- }
- } else if (connection->egress_vlan_tag != NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED) {
- outdev = __vlan_find_dev_deep(outdev, connection->egress_vlan_tag);
+ if (outdev == NULL) {
+ /*
+ * Possible sync for a deleted interface
+ */
+ return;
}
- /*
- * Check if we have a bridge to update
- */
- if (!is_bridge_port(indev) && !is_bridge_port(outdev))
- return;
+ if (is_lag_slave(outdev)) {
+ if (outdev->master == NULL) {
+ NSS_CONNMGR_DEBUG_TRACE("Could not find master for LAG slave %s\n", outdev->name);
+ return;
+ }
+ outdev = outdev->master;
+ } else if (connection->egress_vlan_tag != NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED) {
+ outdev = __vlan_find_dev_deep(outdev, connection->egress_vlan_tag);
+ if (outdev == NULL) {
+ /*
+ * Possible sync for a deleted VLAN interface
+ */
+ return;
+ }
+ }
- /*
- * Update bridge device statistics for routing flows that have
- * a bridge in the path. We should avoid updating bridge device
- * for flows that are forwrded within the bridge.
- */
if (is_bridge_port(indev))
{
/*
* Refresh bridge MAC table if necessary
*/
- if (!sync->final_sync) {
+ if (!sync->final_sync && sync->flow_rx_packet_count) {
br_refresh_fdb_entry(indev, connection->src_mac_addr);
}
+ /*
+ * Update bridge interface stats for L3 flows involving a bridge
+ */
if (indev->master != outdev->master) {
stats.rx_packets = sync->flow_rx_packet_count;
stats.rx_bytes = sync->flow_rx_byte_count;
@@ -2042,10 +2095,13 @@
/*
* Refresh bridge MAC table if necessary
*/
- if (!sync->final_sync) {
+ if (!sync->final_sync && sync->return_rx_packet_count) {
br_refresh_fdb_entry(outdev, connection->dest_mac_addr);
}
+ /*
+ * Update bridge interface stats for L3 flows involving a bridge
+ */
if (indev->master != outdev->master) {
stats.rx_packets = sync->return_rx_packet_count;
stats.rx_bytes = sync->return_rx_byte_count;
diff --git a/nss_tun6rd.c b/nss_tun6rd.c
index b664b7e..dd8fffb 100755
--- a/nss_tun6rd.c
+++ b/nss_tun6rd.c
@@ -405,6 +405,15 @@
* 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);