LCOV - code coverage report
Current view: top level - plugins/pppoe - pppoe.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 32 34 94.1 %
Date: 2023-07-05 22:20:52 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * Copyright (c) 2017 Intel and/or its affiliates.
       4             :  * Licensed under the Apache License, Version 2.0 (the "License");
       5             :  * you may not use this file except in compliance with the License.
       6             :  * You may obtain a copy of the License at:
       7             :  *
       8             :  *     http://www.apache.org/licenses/LICENSE-2.0
       9             :  *
      10             :  * Unless required by applicable law or agreed to in writing, software
      11             :  * distributed under the License is distributed on an "AS IS" BASIS,
      12             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13             :  * See the License for the specific language governing permissions and
      14             :  * limitations under the License.
      15             :  *------------------------------------------------------------------
      16             :  */
      17             : 
      18             : #ifndef _PPPOE_H
      19             : #define _PPPOE_H
      20             : 
      21             : #include <vnet/plugin/plugin.h>
      22             : #include <vppinfra/lock.h>
      23             : #include <vppinfra/error.h>
      24             : #include <vppinfra/hash.h>
      25             : #include <vnet/vnet.h>
      26             : #include <vnet/ip/ip.h>
      27             : #include <vnet/ethernet/ethernet.h>
      28             : #include <vnet/ip/ip4_packet.h>
      29             : #include <vnet/ip/ip6_packet.h>
      30             : #include <vnet/dpo/dpo.h>
      31             : #include <vnet/adj/adj_types.h>
      32             : #include <vnet/fib/fib_table.h>
      33             : #include <vlib/vlib.h>
      34             : #include <vppinfra/bihash_8_8.h>
      35             : 
      36             : 
      37             : typedef struct
      38             : {
      39             :   u8 ver_type;
      40             :   u8 code;
      41             :   u16 session_id;
      42             :   u16 length;
      43             :   u16 ppp_proto;
      44             : } pppoe_header_t;
      45             : 
      46             : #define PPPOE_VER_TYPE 0x11
      47             : #define PPPOE_PADS 0x65
      48             : 
      49             : typedef struct
      50             : {
      51             :   /* Required for pool_get_aligned  */
      52             :   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
      53             : 
      54             :   /* pppoe session_id in HOST byte order */
      55             :   u16 session_id;
      56             : 
      57             :   /* session client addresses */
      58             :   ip46_address_t client_ip;
      59             : 
      60             :   /* the index of tx interface for pppoe encaped packet */
      61             :   u32 encap_if_index;
      62             : 
      63             :   /** FIB indices - inner IP packet lookup here */
      64             :   u32 decap_fib_index;
      65             : 
      66             :   u8 local_mac[6];
      67             :   u8 client_mac[6];
      68             : 
      69             :   /* vnet intfc index */
      70             :   u32 sw_if_index;
      71             :   u32 hw_if_index;
      72             : 
      73             : } pppoe_session_t;
      74             : 
      75             : #define foreach_pppoe_input_next        \
      76             : _(DROP, "error-drop")                  \
      77             : _(IP4_INPUT, "ip4-input")              \
      78             : _(IP6_INPUT, "ip6-input" )             \
      79             : _(CP_INPUT, "pppoe-cp-dispatch" )      \
      80             : 
      81             : typedef enum
      82             : {
      83             : #define _(s,n) PPPOE_INPUT_NEXT_##s,
      84             :   foreach_pppoe_input_next
      85             : #undef _
      86             :     PPPOE_INPUT_N_NEXT,
      87             : } pppoe_input_next_t;
      88             : 
      89             : typedef enum
      90             : {
      91             : #define pppoe_error(n,s) PPPOE_ERROR_##n,
      92             : #include <pppoe/pppoe_error.def>
      93             : #undef pppoe_error
      94             :   PPPOE_N_ERROR,
      95             : } pppoe_input_error_t;
      96             : 
      97             : extern char *pppoe_error_strings[];
      98             : 
      99             : #define MTU 1500
     100             : #define MTU_BUFFERS ((MTU + vlib_buffer_get_default_data_size(vm) - 1) / vlib_buffer_get_default_data_size(vm))
     101             : #define NUM_BUFFERS_TO_ALLOC 32
     102             : 
     103             : /*
     104             :  * The size of pppoe session table
     105             :  */
     106             : #define PPPOE_NUM_BUCKETS (64 * 1024)
     107             : #define PPPOE_MEMORY_SIZE (8<<20)
     108             : 
     109             : /* *INDENT-OFF* */
     110             : /*
     111             :  * The PPPoE key is the mac address and session ID
     112             :  */
     113             : typedef struct
     114             : {
     115             :   union
     116             :   {
     117             :     struct
     118             :     {
     119             :       u16 session_id;
     120             :       u8 mac[6];
     121             :     } fields;
     122             :     struct
     123             :     {
     124             :       u32 w0;
     125             :       u32 w1;
     126             :     } words;
     127             :     u64 raw;
     128             :   };
     129             : } pppoe_entry_key_t;
     130             : /* *INDENT-ON* */
     131             : 
     132             : /* *INDENT-OFF* */
     133             : /*
     134             :  * The PPPoE entry results
     135             :  */
     136             : typedef struct
     137             : {
     138             :   union
     139             :   {
     140             :     struct
     141             :     {
     142             :       u32 sw_if_index;
     143             : 
     144             :       u32 session_index;
     145             : 
     146             :     } fields;
     147             :     u64 raw;
     148             :   };
     149             : }  pppoe_entry_result_t;
     150             : /* *INDENT-ON* */
     151             : 
     152             : typedef struct
     153             : {
     154             :   /* Vector of encap session instances, */
     155             :   pppoe_session_t *sessions;
     156             : 
     157             :   /* For CP:  vector of CP path */
     158             :     BVT (clib_bihash) link_table;
     159             : 
     160             :   /* For DP:  vector of DP path */
     161             :     BVT (clib_bihash) session_table;
     162             : 
     163             :   /* Free vlib hw_if_indices */
     164             :   u32 *free_pppoe_session_hw_if_indices;
     165             : 
     166             :   /* Mapping from sw_if_index to session index */
     167             :   u32 *session_index_by_sw_if_index;
     168             : 
     169             :   /* used for pppoe cp path */
     170             :   u32 cp_if_index;
     171             : 
     172             :   /* API message ID base */
     173             :   u16 msg_id_base;
     174             : 
     175             :   /* convenience */
     176             :   vlib_main_t *vlib_main;
     177             :   vnet_main_t *vnet_main;
     178             : 
     179             : } pppoe_main_t;
     180             : 
     181             : extern pppoe_main_t pppoe_main;
     182             : 
     183             : extern vlib_node_registration_t pppoe_input_node;
     184             : extern vlib_node_registration_t pppoe_cp_dispatch_node;
     185             : 
     186             : typedef struct
     187             : {
     188             :   u8 is_add;
     189             :   u8 is_ip6;
     190             :   u16 session_id;
     191             :   ip46_address_t client_ip;
     192             :   u32 encap_if_index;
     193             :   u32 decap_fib_index;
     194             :   u8 local_mac[6];
     195             :   u8 client_mac[6];
     196             : } vnet_pppoe_add_del_session_args_t;
     197             : 
     198             : int vnet_pppoe_add_del_session
     199             :   (vnet_pppoe_add_del_session_args_t * a, u32 * sw_if_indexp);
     200             : 
     201             : typedef struct
     202             : {
     203             :   u8 is_add;
     204             :   u32 client_if_index;
     205             :   u32 cp_if_index;
     206             : } vnet_pppoe_add_del_tap_args_t;
     207             : 
     208             : int pppoe_add_del_cp (u32 cp_if_index, u8 is_add);
     209             : 
     210             : always_inline u64
     211          71 : pppoe_make_key (u8 * mac_address, u16 session_id)
     212             : {
     213             :   u64 temp;
     214             : 
     215             :   /*
     216             :    * The mac address in memory is A:B:C:D:E:F
     217             :    * The session_id in register is H:L
     218             :    */
     219             : #if CLIB_ARCH_IS_LITTLE_ENDIAN
     220             :   /*
     221             :    * Create the in-register key as F:E:D:C:B:A:H:L
     222             :    * In memory the key is L:H:A:B:C:D:E:F
     223             :    */
     224          71 :   temp = *((u64 *) (mac_address)) << 16;
     225          71 :   temp = (temp & ~0xffff) | (u64) (session_id);
     226             : #else
     227             :   /*
     228             :    * Create the in-register key as H:L:A:B:C:D:E:F
     229             :    * In memory the key is H:L:A:B:C:D:E:F
     230             :    */
     231             :   temp = *((u64 *) (mac_address)) >> 16;
     232             :   temp = temp | (((u64) session_id) << 48);
     233             : #endif
     234             : 
     235          71 :   return temp;
     236             : }
     237             : 
     238             : /**
     239             :  * Perform learning on one packet based on the mac table lookup result.
     240             :  * */
     241             : static_always_inline void
     242          34 : pppoe_learn_process (BVT (clib_bihash) * table,
     243             :                      u32 sw_if_index0,
     244             :                      pppoe_entry_key_t * key0,
     245             :                      pppoe_entry_key_t * cached_key,
     246             :                      u32 * bucket0, pppoe_entry_result_t * result0)
     247             : {
     248             :   /* Check mac table lookup result */
     249          34 :   if (PREDICT_TRUE (result0->fields.sw_if_index == sw_if_index0))
     250             :     {
     251             :       /*
     252             :        * The entry was in the table, and the sw_if_index matched, the normal case
     253             :        */
     254          30 :       return;
     255             :     }
     256           4 :   else if (result0->fields.sw_if_index == ~0)
     257             :     {
     258             :       /* The entry was not in table, so add it  */
     259           4 :       result0->fields.sw_if_index = sw_if_index0;
     260           4 :       result0->fields.session_index = ~0;
     261           4 :       cached_key->raw = ~0;  /* invalidate the cache */
     262             :     }
     263             :   else
     264             :     {
     265             :       /* The entry was in the table, but with the wrong sw_if_index mapping (mac move) */
     266           0 :       result0->fields.sw_if_index = sw_if_index0;
     267             :     }
     268             : 
     269             :   /* Update the entry */
     270             :   BVT (clib_bihash_kv) kv;
     271           4 :   kv.key = key0->raw;
     272           4 :   kv.value = result0->raw;
     273           4 :   BV (clib_bihash_add_del) (table, &kv, 1 /* is_add */ );
     274             : }
     275             : 
     276             : static_always_inline void
     277          55 : pppoe_lookup_1 (BVT (clib_bihash) * table,
     278             :                 pppoe_entry_key_t * cached_key,
     279             :                 pppoe_entry_result_t * cached_result,
     280             :                 u8 * mac0,
     281             :                 u16 session_id0,
     282             :                 pppoe_entry_key_t * key0,
     283             :                 u32 * bucket0, pppoe_entry_result_t * result0)
     284             : {
     285             :   /* set up key */
     286          55 :   key0->raw = pppoe_make_key (mac0, session_id0);
     287          55 :   *bucket0 = ~0;
     288             : 
     289          55 :   if (key0->raw == cached_key->raw)
     290             :     {
     291             :       /* Hit in the one-entry cache */
     292           0 :       result0->raw = cached_result->raw;
     293             :     }
     294             :   else
     295             :     {
     296             :       /* Do a regular session table lookup */
     297             :       BVT (clib_bihash_kv) kv;
     298             : 
     299          55 :       kv.key = key0->raw;
     300          55 :       kv.value = ~0ULL;
     301          55 :       BV (clib_bihash_search_inline) (table, &kv);
     302          55 :       result0->raw = kv.value;
     303             : 
     304             :       /* Update one-entry cache */
     305          55 :       cached_key->raw = key0->raw;
     306          55 :       cached_result->raw = result0->raw;
     307             :     }
     308          55 : }
     309             : 
     310             : static_always_inline void
     311          16 : pppoe_update_1 (BVT (clib_bihash) * table,
     312             :                 u8 * mac0,
     313             :                 u16 session_id0,
     314             :                 pppoe_entry_key_t * key0,
     315             :                 u32 * bucket0, pppoe_entry_result_t * result0)
     316             : {
     317             :   /* set up key */
     318          16 :   key0->raw = pppoe_make_key (mac0, session_id0);
     319          16 :   *bucket0 = ~0;
     320             : 
     321             :   /* Update the entry */
     322             :   BVT (clib_bihash_kv) kv;
     323          16 :   kv.key = key0->raw;
     324          16 :   kv.value = result0->raw;
     325          16 :   BV (clib_bihash_add_del) (table, &kv, 1 /* is_add */ );
     326             : 
     327          16 : }
     328             : #endif /* _PPPOE_H */
     329             : 
     330             : /*
     331             :  * fd.io coding-style-patch-verification: ON
     332             :  *
     333             :  * Local Variables:
     334             :  * eval: (c-set-style "gnu")
     335             :  * End:
     336             :  */

Generated by: LCOV version 1.14