blob: 4b20311683b30163f62c068dd1c1b3f2771e09ff [file] [log] [blame]
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +05301/*
2 * sfe_pppoe.c
3 * API for shortcut forwarding engine PPPoE flows
4 *
Guduri Prathyusha5f27e232022-01-06 14:39:04 +05305 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +05306 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <linux/skbuff.h>
21#include <linux/if_pppox.h>
22#include <linux/ppp_defs.h>
23
24#include "sfe_debug.h"
25#include "sfe_api.h"
26#include "sfe.h"
27#include "sfe_pppoe.h"
28
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053029/*
30 * sfe_pppoe_add_header()
31 * Add PPPoE header.
32 *
33 * skb->data will point to PPPoE header after the function
34 */
Wayne Tanbb7f1782021-12-13 11:16:04 -080035void sfe_pppoe_add_header(struct sk_buff *skb, u16 pppoe_session_id, u16 ppp_protocol)
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053036{
37 u16 *l2_header;
38 struct pppoe_hdr *ph;
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053039 struct sfe_ppp_hdr *ppp;
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053040 u16 *l3_header = (u16 *)skb->data;
41
42 /*
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053043 * PPPoE header (6 bytes) + PPP header (2 bytes)
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053044 *
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053045 * Hence move by 8 bytes to accomodate PPPoE header
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053046 */
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053047 l2_header = l3_header - ((sizeof(struct pppoe_hdr) + sizeof(struct sfe_ppp_hdr)) / 2);
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053048
49 /*
50 * Headers in skb will look like in below sequence
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053051 * | PPPoE hdr(6 bytes) | PPP hdr (2 bytes) | L3 hdr |
52 *
53 * The length field in the PPPoE header indicates the length of the PPPoE payload which
54 * consists of a 2-byte PPP header plus a skb->len.
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053055 */
56 ph = (struct pppoe_hdr *)l2_header;
57 ph->ver = 1;
58 ph->type = 1;
59 ph->code = 0;
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053060 ph->sid = htons(pppoe_session_id);
61 ph->length = htons(skb->len + sizeof(struct sfe_ppp_hdr));
62 skb->protocol = htons(ETH_P_PPP_SES);
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053063
64 /*
65 * Insert the PPP header protocol
66 */
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053067 ppp = (struct sfe_ppp_hdr *)(l2_header + (sizeof(struct pppoe_hdr) / 2));
68 ppp->protocol = htons(ppp_protocol);
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053069
70 /*
71 * L2 header offset will point to PPPoE header,
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053072 */
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053073 __skb_push(skb, (sizeof(struct pppoe_hdr) + sizeof(struct sfe_ppp_hdr)));
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053074}
75
76/*
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053077 * sfe_pppoe_parse_hdr()
78 * Parse PPPoE header
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053079 *
80 * Returns true if the packet is good for further processing.
81 */
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053082bool sfe_pppoe_parse_hdr(struct sk_buff *skb, struct sfe_l2_info *l2_info)
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053083{
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053084 unsigned int len;
85 int pppoe_len;
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053086 struct sfe_ppp_hdr *ppp;
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053087 struct pppoe_hdr *ph = (struct pppoe_hdr *)skb->data;
88
89 /*
90 * Check that we have space for PPPoE header here.
91 */
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053092 if (unlikely(!pskb_may_pull(skb, (sizeof(struct pppoe_hdr) + sizeof(struct sfe_ppp_hdr))))) {
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053093 DEBUG_TRACE("%px: packet too short for PPPoE header\n", skb);
94 return false;
95 }
96
97 len = skb->len;
98 pppoe_len = ntohs(ph->length);
99 if (unlikely(len < pppoe_len)) {
100 DEBUG_TRACE("%px: len: %u is too short to %u\n", skb, len, pppoe_len);
101 return false;
102 }
103
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530104 ppp = (struct sfe_ppp_hdr *)((u8*)ph + sizeof(*ph));
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +0530105
106 /*
107 * Converting PPP protocol values to ether type protocol values
108 */
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530109 switch(ntohs(ppp->protocol)) {
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +0530110 case PPP_IP:
111 sfe_l2_protocol_set(l2_info, ETH_P_IP);
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530112 break;
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +0530113
114 case PPP_IPV6:
115 sfe_l2_protocol_set(l2_info, ETH_P_IPV6);
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530116 break;
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +0530117
118 case PPP_LCP:
119 DEBUG_TRACE("%px: LCP packets are not supported in SFE\n", skb);
120 return false;
121
122 default:
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530123 DEBUG_TRACE("%px: Unsupported protocol : %d in PPP header\n", skb, ntohs(ppp->protocol));
124 return false;
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +0530125 }
126
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530127 sfe_l2_parse_flag_set(l2_info, SFE_L2_PARSE_FLAGS_PPPOE_INGRESS);
128 sfe_l2_pppoe_hdr_offset_set(l2_info, (skb->data - skb->head));
129 sfe_l2_hdr_size_set(l2_info, (sizeof(struct pppoe_hdr) + sizeof(struct sfe_ppp_hdr)));
130
131 return true;
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +0530132}