[qca-nss-sfe] Add Tx support for PPPoE
Change-Id: Iae53d1eb116ff847457c2da2864ecd21ad8ae0be
Signed-off-by: Guduri Prathyusha <quic_gprathyu@quicinc.com>
diff --git a/sfe_pppoe.c b/sfe_pppoe.c
new file mode 100644
index 0000000..4b74185
--- /dev/null
+++ b/sfe_pppoe.c
@@ -0,0 +1,82 @@
+/*
+ * sfe_pppoe.c
+ * API for shortcut forwarding engine PPPoE flows
+ *
+ * Copyright (c) 2021 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
+ * 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 <linux/skbuff.h>
+#include <linux/if_pppox.h>
+#include <linux/ppp_defs.h>
+
+#include "sfe_debug.h"
+#include "sfe_api.h"
+#include "sfe.h"
+#include "sfe_pppoe.h"
+
+#define SFE_PPPOE_HEADER_SIZE (sizeof(struct pppoe_hdr) + 2)
+
+/*
+ * sfe_pppoe_add_header()
+ * Add PPPoE header.
+ *
+ * skb->data will point to PPPoE header after the function
+ */
+int sfe_pppoe_add_header(struct sk_buff *skb, u16 pppoe_session_id, u16 ppp_protocol)
+{
+ u16 *l2_header;
+ struct pppoe_hdr *ph;
+ u16 *l3_header = (u16 *)skb->data;
+
+ /*
+ * Check that we have space for PPPoE header and PPP header (2 bytes)
+ */
+ if (unlikely(!pskb_may_pull(skb, SFE_PPPOE_HEADER_SIZE))) {
+ DEBUG_TRACE("%px: Not enough headroom for PPPoE header \n", skb);
+ return 0;
+ }
+
+ /*
+ * PPPoE header (8 bytes) + PPP header (2 bytes)
+ *
+ * Hence move by 10 bytes to accomodate PPPoE header
+ */
+ l2_header = l3_header - (SFE_PPPOE_HEADER_SIZE / 2);
+
+ /*
+ * Headers in skb will look like in below sequence
+ * | PPPoE hdr(10 bytes) | L3 hdr |
+ */
+ ph = (struct pppoe_hdr *)l2_header;
+ ph->ver = 1;
+ ph->type = 1;
+ ph->code = 0;
+ ph->sid = pppoe_session_id;
+ ph->length = skb->len;
+ skb->protocol = cpu_to_be16(ETH_P_PPP_SES);
+
+ /*
+ * Insert the PPP header protocol
+ */
+ *(l2_header + 4) = ppp_protocol;
+
+ /*
+ * L2 header offset will point to PPPoE header,
+ * since sfe_ipv4_recv_tcp/udp() does skb_push by ETH_HLEN before adding L2 header.
+ */
+ __skb_push(skb, SFE_PPPOE_HEADER_SIZE);
+
+ return 1;
+}