| /* |
| * Copyright (c) 2009 Mindspeed Technologies, Inc. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| * |
| * |
| */ |
| |
| |
| #ifndef _MODULE_TUNNEL_H_ |
| #define _MODULE_TUNNEL_H_ |
| |
| #include "channels.h" |
| #include "modules.h" |
| #include "fpart.h" |
| #include "fe.h" |
| #include "module_ethernet.h" |
| #include "layer2.h" |
| #include "module_ipv6.h" |
| #include "module_ipv4.h" |
| |
| |
| #define TNL_MAX_HEADER (40 + 14 + 2) |
| #define TNL_MAX_TUNNEL 2 |
| |
| |
| #define TNL_STATE_FREE 0x00 |
| #define TNL_STATE_CREATED 0x01 |
| #define TNL_STATE_ENABLED 0x02 |
| #define TNL_STATE_SA_COMPLETE 0x04 |
| #define TNL_STATE_SAREPLY_COMPLETE 0x08 |
| #define TNL_STATE_REMOTE_ANY 0x10 |
| |
| |
| #define TNL_NOSET_PRIV 0 |
| #define TNL_SET_PRIV 1 |
| |
| enum TNL_MODE { |
| TNL_MODE_ETHERIP, |
| TNL_MODE_6O4, |
| TNL_MODE_4O6, |
| }; |
| |
| enum SAM_ID_CONV_TYPE { |
| SAM_ID_CONV_NONE =0, |
| SAM_ID_CONV_DUPSPORT =1, |
| SAM_ID_CONV_PSID =2, |
| }; |
| |
| #define TNL_ETHERIP_VERSION 0x3000 |
| #define TNL_ETHERIP_HDR_LEN 2 |
| |
| //#define TNL_DBG |
| #undef TNL_DBG |
| |
| #ifdef TNL_DBG |
| /* debug entries */ |
| enum TNL_DBG_SLOT { |
| TNL_DBG_START = 0, |
| TNL_DBG_NUM_ENTRIES, |
| TNL_DBG_COMPLETE, |
| TNL_DBG_SA_IN_NOMATCH, |
| TNL_DBG_SANUM_IN_NOMATCH, |
| TNL_DBG_TNL_IN_NOMATCH, |
| TNL_DBG_IN_RXBRIDGE, |
| TNL_DBG_IN_EXCEPT, |
| TNL_DBG_OUT_EXCEPT_1, |
| TNL_DBG_OUT_EXCEPT_2, |
| TNL_DBG_OUT_EXCEPT_3, |
| TNL_DBG_L2BRIDGE_NO_MATCH, |
| TNL_DBG_END, |
| }; |
| |
| /* debug flags */ |
| #define TNL_DBG_SA_COMPLETE 0x2 |
| #define TNL_DBG_SAREPLY_COMPLETE 0x4 |
| #endif |
| |
| |
| /*********************************** |
| * Tunnel API Command and Entry strutures |
| * |
| ************************************/ |
| |
| typedef struct _tTNLCommand_create { |
| U8 name[16]; |
| U32 local[4]; |
| U32 remote[4]; |
| U8 output_device[16]; |
| U8 mode; |
| /* options */ |
| U8 secure; |
| U8 elim; |
| U8 hlim; |
| U32 fl; |
| U16 frag_off; |
| U16 enabled; |
| U32 route_id; |
| }TNLCommand_create , *PTNLCommand_create; |
| |
| |
| typedef struct _tTNLCommand_delete { |
| U8 name[16]; |
| }TNLCommand_delete, *PTNLCommand_delete; |
| |
| |
| typedef struct _tTNLCommand_ipsec { |
| U8 name[16]; |
| U16 SA_nr; |
| U16 SAReply_nr; |
| U16 SA_handle[4]; |
| U16 SAReply_handle[4]; |
| } TNLCommand_ipsec, *PTNLCommand_ipsec; |
| |
| typedef struct _tTNLCommand_query{ |
| U16 result; |
| U16 unused; |
| U8 name[16]; |
| U32 local[4]; |
| U32 remote[4]; |
| U8 mode; |
| U8 secure; |
| U8 elim; |
| U8 hlim; |
| U32 fl; |
| U16 frag_off; |
| U16 enabled; |
| U32 route_id; |
| }TNLCommand_query , *PTNLCommand_query; |
| |
| typedef struct { |
| int port_set_id; /* Port Set ID */ |
| int port_set_id_length; /* Port Set ID length */ |
| int psid_offset; /* PSID offset */ |
| }sam_port_info_t; |
| |
| typedef struct _tTNLCommand_IdConvDP { |
| U16 IdConvStatus; |
| U16 Pad; |
| }TNLCommand_IdConvDP, *pTNLCommand_IdConvDP; |
| |
| typedef struct _tTNLCommand_IdConvPsid { |
| U8 name[16]; |
| sam_port_info_t sam_port_info; |
| U32 IdConvStatus:1, |
| unused:31; |
| }TNLCommand_IdConvPsid, *pTNLCommand_IdConvPsid; |
| |
| |
| |
| #if !defined(COMCERTO_2000) |
| |
| typedef struct _tTnlEntry{ |
| struct itf itf; |
| |
| union { |
| U8 header[TNL_MAX_HEADER]; |
| ipv4_hdr_t header_v4; |
| }; |
| U8 header_size; |
| U8 mode; |
| U8 proto; |
| U8 secure; |
| U8 state; |
| U32 local[4]; |
| U32 remote[4]; |
| U8 hlim; |
| U8 elim; |
| U8 output_proto; |
| U32 fl; |
| U16 frag_off; |
| PRouteEntry pRtEntry; |
| U16 SAReply_nr; |
| U16 SA_nr; |
| U16 hSAEntry_in[SA_MAX_OP]; |
| U16 hSAEntry_out[SA_MAX_OP]; |
| U32 route_id; |
| int tunnel_index; |
| U16 sam_abit; |
| U16 sam_abit_max; |
| U16 sam_kbit; |
| U16 sam_mbit; |
| U16 sam_mbit_max; |
| U8 sam_mbit_len; |
| U8 sam_abit_len; |
| U8 sam_kbit_len; |
| U8 sam_id_conv_enable; |
| }TnlEntry, *PTnlEntry; |
| |
| #elif defined(COMCERTO_2000_CONTROL) |
| |
| typedef struct _tTnlEntry{ |
| struct itf itf; |
| struct hw_route route; |
| |
| union { |
| U8 header[TNL_MAX_HEADER]; |
| ipv4_hdr_t header_v4; |
| }; |
| U8 header_size; |
| U8 mode; |
| U8 proto; |
| U8 secure; |
| U8 state; |
| U8 hlim; |
| U8 elim; |
| U8 output_proto; |
| U32 local[4]; |
| U32 remote[4]; |
| U32 fl; |
| U16 frag_off; |
| U16 SAReply_nr; |
| U16 SA_nr; |
| U16 hSAEntry_in[SA_MAX_OP]; |
| U16 hSAEntry_out[SA_MAX_OP]; |
| U16 sam_abit; |
| U16 sam_abit_max; |
| U16 sam_kbit; |
| U16 sam_mbit; |
| U16 sam_mbit_max; |
| U8 sam_mbit_len; |
| U8 sam_abit_len; |
| U8 sam_kbit_len; |
| U8 sam_id_conv_enable; |
| |
| // following entries not used in data path |
| U32 route_id; |
| PRouteEntry pRtEntry; |
| int tunnel_index; |
| }TnlEntry, *PTnlEntry; |
| |
| |
| typedef struct tTNL_context { |
| TnlEntry tunnel_table[TNL_MAX_TUNNEL]; |
| }TNL_context; |
| |
| #else // defined(COMCERTO_2000) |
| |
| typedef struct _tTnlEntry{ |
| struct itf itf; |
| RouteEntry route; |
| |
| union { |
| U8 header[TNL_MAX_HEADER]; |
| ipv4_hdr_t header_v4; |
| }; |
| U8 header_size; |
| U8 mode; |
| U8 proto; |
| U8 secure; |
| U8 state; |
| U8 hlim; |
| U8 elim; |
| U8 output_proto; |
| U32 local[4]; |
| U32 remote[4]; |
| U32 fl; |
| U16 frag_off; |
| U16 SAReply_nr; |
| U16 SA_nr; |
| U16 hSAEntry_in[SA_MAX_OP]; |
| U16 hSAEntry_out[SA_MAX_OP]; |
| U16 sam_abit; |
| U16 sam_abit_max; |
| U16 sam_kbit; |
| U16 sam_mbit; |
| U16 sam_mbit_max; |
| U8 sam_mbit_len; |
| U8 sam_abit_len; |
| U8 sam_kbit_len; |
| U8 sam_id_conv_enable; |
| // following entries not used in data path |
| U32 unused_route_id; |
| U32 unused_pRtEntry; |
| int unused_tunnel_index; |
| }TnlEntry, *PTnlEntry; |
| |
| |
| typedef struct tTNL_context { |
| TnlEntry tunnel_table[TNL_MAX_TUNNEL]; |
| }TNL_context; |
| |
| #endif /* !defined(COMCERTO_2000) */ |
| |
| extern struct tTNL_context gTNLCtx; |
| |
| void M_TNL_OUT_process_packet(PMetadata mtd); |
| void M_TNL_IN_process_packet(PMetadata mtd); |
| |
| #if !defined(COMCERTO_2000) |
| BOOL M_tnl_in_init(PModuleDesc pModule); |
| BOOL M_tnl_out_init(PModuleDesc pModule); |
| void M_tnl_entry_in(void); |
| void M_tnl_entry_out(void); |
| #else |
| int tunnel_init(void); |
| void tunnel_exit(void); |
| #endif |
| |
| int M_tnl_update_header(PTnlEntry pTunnelEntry, PMetadata mtd); |
| U16 Tnl_Get_Next_Hash_Entry(PTNLCommand_query pTnlCmd, int reset_action); |
| #ifdef TNL_DBG |
| void M_tnl_debug(void); |
| #endif |
| |
| PTnlEntry M_tnl6_match_ingress(PMetadata mtd, ipv6_hdr_t *ipv6_hdr, U8 proto, U8 set_tnl); |
| PTnlEntry M_tnl4_match_ingress(PMetadata mtd, ipv4_hdr_t *ipv4_hdr, U8 proto); |
| |
| |
| static __inline void * M_tnl_add_header(PMetadata mtd, PTnlEntry pTnlEntry) |
| { |
| mtd->offset -= pTnlEntry->header_size; |
| mtd->length += pTnlEntry->header_size; |
| SFL_memcpy(mtd->data + mtd->offset, pTnlEntry->header, pTnlEntry->header_size); |
| M_tnl_update_header(pTnlEntry, mtd); |
| return (mtd->data + mtd->offset); |
| } |
| |
| |
| /* Inherited from linux-2.6.21.1/include/net/inet_ecn.h for tos management in 6o4 tunnels */ |
| enum { |
| INET_ECN_NOT_ECT = 0, |
| INET_ECN_ECT_1 = 1, |
| INET_ECN_ECT_0 = 2, |
| INET_ECN_CE = 3, |
| INET_ECN_MASK = 3, |
| }; |
| |
| static inline int INET_ECN_is_ce(U8 dsfield) |
| { |
| return (dsfield & INET_ECN_MASK) == INET_ECN_CE; |
| } |
| |
| static inline U8 INET_ECN_encapsulate(U8 outer, U8 inner) |
| { |
| outer &= ~INET_ECN_MASK; |
| outer |= !INET_ECN_is_ce(inner) ? (inner & INET_ECN_MASK) : INET_ECN_ECT_0; |
| return outer; |
| } |
| |
| static inline void ipv6_change_dsfield(ipv6_hdr_t *ipv6h,U8 mask, U8 value) |
| { |
| U16 tmp; |
| |
| tmp = ntohs(*(U16*)ipv6h); |
| tmp = (tmp & ((mask << 4) | 0xf00f)) | (value << 4); |
| *(U16*) ipv6h = htons(tmp); |
| } |
| |
| |
| #endif /* _MODULE_TUNNEL_H_ */ |