blob: 770a77d5622da218680b514a8a5aafc206f42e43 [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>
Nitin Shetty9af87d42022-02-11 16:25:29 +053023#include <asm/unaligned.h>
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053024
25#include "sfe_debug.h"
26#include "sfe_api.h"
27#include "sfe.h"
28#include "sfe_pppoe.h"
29
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053030/*
31 * sfe_pppoe_add_header()
32 * Add PPPoE header.
33 *
34 * skb->data will point to PPPoE header after the function
35 */
Wayne Tanbb7f1782021-12-13 11:16:04 -080036void sfe_pppoe_add_header(struct sk_buff *skb, u16 pppoe_session_id, u16 ppp_protocol)
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053037{
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053038 struct pppoe_hdr *ph;
Nitin Shetty9af87d42022-02-11 16:25:29 +053039 unsigned char *pp;
40 unsigned int data_len;
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053041
42 /*
Nitin Shetty9af87d42022-02-11 16:25:29 +053043 * Insert the PPP header protocol
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053044 */
Nitin Shetty9af87d42022-02-11 16:25:29 +053045 pp = __skb_push(skb, 2);
46 put_unaligned_be16(ppp_protocol, pp);
47
48 data_len = skb->len;
49
50 ph = (struct pppoe_hdr *)__skb_push(skb, sizeof(*ph));
51 skb_reset_network_header(skb);
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053052
53 /*
54 * Headers in skb will look like in below sequence
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053055 * | PPPoE hdr(6 bytes) | PPP hdr (2 bytes) | L3 hdr |
56 *
57 * The length field in the PPPoE header indicates the length of the PPPoE payload which
58 * consists of a 2-byte PPP header plus a skb->len.
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053059 */
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +053060 ph->ver = 1;
61 ph->type = 1;
62 ph->code = 0;
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053063 ph->sid = htons(pppoe_session_id);
Nitin Shetty9af87d42022-02-11 16:25:29 +053064 ph->length = htons(data_len);
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053065 skb->protocol = htons(ETH_P_PPP_SES);
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053066}
67
68/*
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053069 * sfe_pppoe_parse_hdr()
70 * Parse PPPoE header
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053071 *
72 * Returns true if the packet is good for further processing.
73 */
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053074bool sfe_pppoe_parse_hdr(struct sk_buff *skb, struct sfe_l2_info *l2_info)
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053075{
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053076 unsigned int len;
77 int pppoe_len;
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053078 struct sfe_ppp_hdr *ppp;
Nitin Shetty9af87d42022-02-11 16:25:29 +053079 struct pppoe_hdr *ph = pppoe_hdr(skb);
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053080
81 /*
82 * Check that we have space for PPPoE header here.
83 */
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053084 if (unlikely(!pskb_may_pull(skb, (sizeof(struct pppoe_hdr) + sizeof(struct sfe_ppp_hdr))))) {
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053085 DEBUG_TRACE("%px: packet too short for PPPoE header\n", skb);
86 return false;
87 }
88
89 len = skb->len;
90 pppoe_len = ntohs(ph->length);
91 if (unlikely(len < pppoe_len)) {
92 DEBUG_TRACE("%px: len: %u is too short to %u\n", skb, len, pppoe_len);
93 return false;
94 }
95
Guduri Prathyusha5f27e232022-01-06 14:39:04 +053096 ppp = (struct sfe_ppp_hdr *)((u8*)ph + sizeof(*ph));
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +053097
98 /*
99 * Converting PPP protocol values to ether type protocol values
100 */
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530101 switch(ntohs(ppp->protocol)) {
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +0530102 case PPP_IP:
103 sfe_l2_protocol_set(l2_info, ETH_P_IP);
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530104 break;
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +0530105
106 case PPP_IPV6:
107 sfe_l2_protocol_set(l2_info, ETH_P_IPV6);
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530108 break;
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +0530109
110 case PPP_LCP:
111 DEBUG_TRACE("%px: LCP packets are not supported in SFE\n", skb);
112 return false;
113
114 default:
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530115 DEBUG_TRACE("%px: Unsupported protocol : %d in PPP header\n", skb, ntohs(ppp->protocol));
116 return false;
Guduri Prathyusha647fe3e2021-11-22 19:17:51 +0530117 }
118
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530119 sfe_l2_parse_flag_set(l2_info, SFE_L2_PARSE_FLAGS_PPPOE_INGRESS);
Nitin Shetty9af87d42022-02-11 16:25:29 +0530120 sfe_l2_pppoe_session_id_set(l2_info, ntohs(ph->sid));
121
122 /*
123 * strip PPPoE header
124 */
125 __skb_pull(skb, (sizeof(struct pppoe_hdr) + sizeof(struct sfe_ppp_hdr)));
126 skb_reset_network_header(skb);
Guduri Prathyusha5f27e232022-01-06 14:39:04 +0530127
128 return true;
Guduri Prathyusha79a5fee2021-11-11 17:59:10 +0530129}
Nitin Shetty9af87d42022-02-11 16:25:29 +0530130
131/*
132 * sfe_pppoe_undo_parse()
133 * undo changes done to skb during PPPoE parsing
134 */
135void sfe_pppoe_undo_parse(struct sk_buff *skb, struct sfe_l2_info *l2_info)
136{
137 if (sfe_l2_parse_flag_check(l2_info, SFE_L2_PARSE_FLAGS_PPPOE_INGRESS)) {
138 __skb_push(skb, (sizeof(struct pppoe_hdr) + sizeof(struct sfe_ppp_hdr)));
139 }
140}