[qca-nss-sfe] 802.1Q/802.1ad VLAN support in SFE

Change-Id: I8007484b229b0dac0aff6dc284641b94090539db
Signed-off-by: Wayne Tan <quic_wtan@quicinc.com>
diff --git a/sfe_ipv6_tcp.c b/sfe_ipv6_tcp.c
index 5d43493..85c299b 100644
--- a/sfe_ipv6_tcp.c
+++ b/sfe_ipv6_tcp.c
@@ -29,6 +29,7 @@
 #include "sfe_flow_cookie.h"
 #include "sfe_ipv6.h"
 #include "sfe_pppoe.h"
+#include "sfe_vlan.h"
 
 /*
  * sfe_ipv6_process_tcp_option_sack()
@@ -131,7 +132,7 @@
 	bool bridge_flow;
 
 	/*
-	 * Is our packet too short to contain a valid UDP header?
+	 * Is our packet too short to contain a valid TCP header?
 	 */
 	if (!pskb_may_pull(skb, (sizeof(struct tcphdr) + ihl))) {
 
@@ -190,7 +191,7 @@
 	}
 
 	/*
-	 * If our packet has beern marked as "sync on find" we can't actually
+	 * If our packet has been marked as "sync on find" we can't actually
 	 * forward it in the fast path, but now that we've found an associated
 	 * connection we need sync its status before throw it slow path.
 	 */
@@ -215,6 +216,16 @@
 	}
 #endif
 
+	/*
+	 * Do we expect an ingress VLAN tag for this flow?
+	 */
+	if (unlikely(!sfe_vlan_validate_ingress_tag(skb, cm->ingress_vlan_hdr_cnt, cm->ingress_vlan_hdr, l2_info))) {
+		rcu_read_unlock();
+		sfe_ipv6_exception_stats_inc(si, SFE_IPV6_EXCEPTION_EVENT_INGRESS_VLAN_TAG_MISMATCH);
+		DEBUG_TRACE("VLAN tag mismatch. skb=%px\n", skb);
+		return 0;
+	}
+
 	bridge_flow = !!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_BRIDGE_FLOW);
 
 	/*
@@ -512,6 +523,16 @@
 	}
 
 	/*
+	 * Check if skb has enough headroom to write L2 headers
+	 */
+	if (unlikely(skb_headroom(skb) < cm->l2_hdr_size)) {
+		rcu_read_unlock();
+		DEBUG_WARN("%px: Not enough headroom: %u\n", skb, skb_headroom(skb));
+		sfe_ipv6_exception_stats_inc(si, SFE_IPV6_EXCEPTION_EVENT_NO_HEADROOM);
+		return 0;
+	}
+
+	/*
 	 * From this point on we're good to modify the packet.
 	 */
 
@@ -519,19 +540,11 @@
 	 * For PPPoE flows, add PPPoE header before L2 header is added.
 	 */
 	if (cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_PPPOE_ENCAP) {
-		if (unlikely(!sfe_pppoe_add_header(skb, cm->pppoe_session_id, PPP_IPV6))) {
-			rcu_read_unlock();
-			DEBUG_WARN("%px: PPPoE header addition failed\n", skb);
-			sfe_ipv6_exception_stats_inc(si, SFE_IPV6_EXCEPTION_EVENT_NO_HEADROOM);
-		}
+		sfe_pppoe_add_header(skb, cm->pppoe_session_id, PPP_IPV6);
 		this_cpu_inc(si->stats_pcpu->pppoe_encap_packets_forwarded64);
 	}
 
 	/*
-	 * TODO: VLAN header should be added here when they are supported.
-	 */
-
-	/*
 	 * Update DSCP
 	 */
 	if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK)) {
@@ -614,8 +627,16 @@
 	xmit_dev = cm->xmit_dev;
 	skb->dev = xmit_dev;
 
+
 	/*
-	 * Check to see if we need to write a header.
+	 * Check to see if we need to add VLAN tags
+	 */
+	if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_INSERT_EGRESS_VLAN_TAG)) {
+		sfe_vlan_add_tag(skb, cm->egress_vlan_hdr_cnt, cm->egress_vlan_hdr);
+	}
+
+	/*
+	 * Check to see if we need to write an Ethernet header.
 	 */
 	if (likely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) {
 		if (unlikely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) {