Guduri Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 1 | /* |
| 2 | * sfe_pppoe.c |
| 3 | * API for shortcut forwarding engine PPPoE flows |
| 4 | * |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 5 | * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. |
Guduri Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 6 | * |
| 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 Shetty | 9af87d4 | 2022-02-11 16:25:29 +0530 | [diff] [blame^] | 23 | #include <asm/unaligned.h> |
Guduri Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 24 | |
| 25 | #include "sfe_debug.h" |
| 26 | #include "sfe_api.h" |
| 27 | #include "sfe.h" |
| 28 | #include "sfe_pppoe.h" |
| 29 | |
Guduri Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 30 | /* |
| 31 | * sfe_pppoe_add_header() |
| 32 | * Add PPPoE header. |
| 33 | * |
| 34 | * skb->data will point to PPPoE header after the function |
| 35 | */ |
Wayne Tan | bb7f178 | 2021-12-13 11:16:04 -0800 | [diff] [blame] | 36 | void sfe_pppoe_add_header(struct sk_buff *skb, u16 pppoe_session_id, u16 ppp_protocol) |
Guduri Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 37 | { |
Guduri Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 38 | struct pppoe_hdr *ph; |
Nitin Shetty | 9af87d4 | 2022-02-11 16:25:29 +0530 | [diff] [blame^] | 39 | unsigned char *pp; |
| 40 | unsigned int data_len; |
Guduri Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 41 | |
| 42 | /* |
Nitin Shetty | 9af87d4 | 2022-02-11 16:25:29 +0530 | [diff] [blame^] | 43 | * Insert the PPP header protocol |
Guduri Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 44 | */ |
Nitin Shetty | 9af87d4 | 2022-02-11 16:25:29 +0530 | [diff] [blame^] | 45 | 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 Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 52 | |
| 53 | /* |
| 54 | * Headers in skb will look like in below sequence |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 55 | * | 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 Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 59 | */ |
Guduri Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 60 | ph->ver = 1; |
| 61 | ph->type = 1; |
| 62 | ph->code = 0; |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 63 | ph->sid = htons(pppoe_session_id); |
Nitin Shetty | 9af87d4 | 2022-02-11 16:25:29 +0530 | [diff] [blame^] | 64 | ph->length = htons(data_len); |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 65 | skb->protocol = htons(ETH_P_PPP_SES); |
Guduri Prathyusha | 647fe3e | 2021-11-22 19:17:51 +0530 | [diff] [blame] | 66 | } |
| 67 | |
| 68 | /* |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 69 | * sfe_pppoe_parse_hdr() |
| 70 | * Parse PPPoE header |
Guduri Prathyusha | 647fe3e | 2021-11-22 19:17:51 +0530 | [diff] [blame] | 71 | * |
| 72 | * Returns true if the packet is good for further processing. |
| 73 | */ |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 74 | bool sfe_pppoe_parse_hdr(struct sk_buff *skb, struct sfe_l2_info *l2_info) |
Guduri Prathyusha | 647fe3e | 2021-11-22 19:17:51 +0530 | [diff] [blame] | 75 | { |
Guduri Prathyusha | 647fe3e | 2021-11-22 19:17:51 +0530 | [diff] [blame] | 76 | unsigned int len; |
| 77 | int pppoe_len; |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 78 | struct sfe_ppp_hdr *ppp; |
Nitin Shetty | 9af87d4 | 2022-02-11 16:25:29 +0530 | [diff] [blame^] | 79 | struct pppoe_hdr *ph = pppoe_hdr(skb); |
Guduri Prathyusha | 647fe3e | 2021-11-22 19:17:51 +0530 | [diff] [blame] | 80 | |
| 81 | /* |
| 82 | * Check that we have space for PPPoE header here. |
| 83 | */ |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 84 | if (unlikely(!pskb_may_pull(skb, (sizeof(struct pppoe_hdr) + sizeof(struct sfe_ppp_hdr))))) { |
Guduri Prathyusha | 647fe3e | 2021-11-22 19:17:51 +0530 | [diff] [blame] | 85 | 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 Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 96 | ppp = (struct sfe_ppp_hdr *)((u8*)ph + sizeof(*ph)); |
Guduri Prathyusha | 647fe3e | 2021-11-22 19:17:51 +0530 | [diff] [blame] | 97 | |
| 98 | /* |
| 99 | * Converting PPP protocol values to ether type protocol values |
| 100 | */ |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 101 | switch(ntohs(ppp->protocol)) { |
Guduri Prathyusha | 647fe3e | 2021-11-22 19:17:51 +0530 | [diff] [blame] | 102 | case PPP_IP: |
| 103 | sfe_l2_protocol_set(l2_info, ETH_P_IP); |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 104 | break; |
Guduri Prathyusha | 647fe3e | 2021-11-22 19:17:51 +0530 | [diff] [blame] | 105 | |
| 106 | case PPP_IPV6: |
| 107 | sfe_l2_protocol_set(l2_info, ETH_P_IPV6); |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 108 | break; |
Guduri Prathyusha | 647fe3e | 2021-11-22 19:17:51 +0530 | [diff] [blame] | 109 | |
| 110 | case PPP_LCP: |
| 111 | DEBUG_TRACE("%px: LCP packets are not supported in SFE\n", skb); |
| 112 | return false; |
| 113 | |
| 114 | default: |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 115 | DEBUG_TRACE("%px: Unsupported protocol : %d in PPP header\n", skb, ntohs(ppp->protocol)); |
| 116 | return false; |
Guduri Prathyusha | 647fe3e | 2021-11-22 19:17:51 +0530 | [diff] [blame] | 117 | } |
| 118 | |
Guduri Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 119 | sfe_l2_parse_flag_set(l2_info, SFE_L2_PARSE_FLAGS_PPPOE_INGRESS); |
Nitin Shetty | 9af87d4 | 2022-02-11 16:25:29 +0530 | [diff] [blame^] | 120 | 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 Prathyusha | 5f27e23 | 2022-01-06 14:39:04 +0530 | [diff] [blame] | 127 | |
| 128 | return true; |
Guduri Prathyusha | 79a5fee | 2021-11-11 17:59:10 +0530 | [diff] [blame] | 129 | } |
Nitin Shetty | 9af87d4 | 2022-02-11 16:25:29 +0530 | [diff] [blame^] | 130 | |
| 131 | /* |
| 132 | * sfe_pppoe_undo_parse() |
| 133 | * undo changes done to skb during PPPoE parsing |
| 134 | */ |
| 135 | void 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 | } |