1/*
2 * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 *
16 * $Id: hndctf.h 408190 2013-06-18 00:32:43Z $
17 */
18
19#ifndef _HNDCTF_H_
20#define _HNDCTF_H_
21
22#include <bcmutils.h>
23#include <proto/bcmip.h>
24#include <proto/ethernet.h>
25#include <proto/vlan.h>
26
27/*
28 * Define to enable couting VLAN tx and rx packets and bytes. This could be
29 * disabled if the functionality has impact on performance.
30 */
31#define CTFVLSTATS
32
33#define CTF_ENAB(ci)		(((ci) != NULL) && (ci)->_ctf)
34
35#define CTF_ACTION_TAG		(1 << 0)
36#define CTF_ACTION_UNTAG	(1 << 1)
37#define CTF_ACTION_SNAT		(1 << 2)
38#define CTF_ACTION_DNAT		(1 << 3)
39#define CTF_ACTION_SUSPEND	(1 << 4)
40#define CTF_ACTION_TOS		(1 << 5)
41#define CTF_ACTION_MARK		(1 << 6)
42#define CTF_ACTION_BYTECNT	(1 << 7)
43#define CTF_ACTION_PPPOE_ADD	(1 << 8)
44#define CTF_ACTION_PPPOE_DEL	(1 << 9)
45
46#define CTF_SUSPEND_TCP		(1 << 0)
47#define CTF_SUSPEND_UDP		(1 << 1)
48
49#define	ctf_attach(osh, n, m, c, a) \
50	(ctf_attach_fn ? ctf_attach_fn(osh, n, m, c, a) : NULL)
51#define ctf_forward(ci, p, d)	(ci)->fn.forward(ci, p, d)
52#define ctf_isenabled(ci, d)	(CTF_ENAB(ci) ? (ci)->fn.isenabled(ci, d) : FALSE)
53#define ctf_isbridge(ci, d)	(CTF_ENAB(ci) ? (ci)->fn.isbridge(ci, d) : FALSE)
54#define ctf_enable(ci, d, e, b)	(CTF_ENAB(ci) ? (ci)->fn.enable(ci, d, e, b) : BCME_OK)
55#define ctf_brc_add(ci, b)	(CTF_ENAB(ci) ? (ci)->fn.brc_add(ci, b) : BCME_OK)
56#define ctf_brc_delete(ci, e)	(CTF_ENAB(ci) ? (ci)->fn.brc_delete(ci, e) : BCME_OK)
57#define ctf_brc_update(ci, b)	(CTF_ENAB(ci) ? (ci)->fn.brc_update(ci, b) : BCME_OK)
58#define ctf_brc_lkup(ci, e)	(CTF_ENAB(ci) ? (ci)->fn.brc_lkup(ci, e) : NULL)
59#define ctf_brc_release(ci, b)	do { if (CTF_ENAB(ci)) (ci)->fn.brc_release(ci, b); } while (0)
60#define ctf_ipc_add(ci, i, v6)	(CTF_ENAB(ci) ? (ci)->fn.ipc_add(ci, i, v6) : BCME_OK)
61#define ctf_ipc_delete(ci, i, v6)	\
62	(CTF_ENAB(ci) ? (ci)->fn.ipc_delete(ci, i, v6) : BCME_OK)
63#define ctf_ipc_count_get(ci, i) \
64	(CTF_ENAB(ci) ? (ci)->fn.ipc_count_get(ci, i) : BCME_OK)
65#define ctf_ipc_delete_multi(ci, i, im, v6)	\
66	(CTF_ENAB(ci) ? (ci)->fn.ipc_delete_multi(ci, i, im, v6) : BCME_OK)
67#define ctf_ipc_delete_range(ci, s, e, v6)	\
68	(CTF_ENAB(ci) ? (ci)->fn.ipc_delete_range(ci, s, e, v6) : BCME_OK)
69#define ctf_ipc_action(ci, s, e, am, v6) \
70	(CTF_ENAB(ci) ? (ci)->fn.ipc_action(ci, s, e, am, v6) : BCME_OK)
71#define ctf_ipc_lkup(ci, i, v6)	\
72	(CTF_ENAB(ci) ? (ci)->fn.ipc_lkup(ci, i, v6) : NULL)
73#ifdef CTF_IPV6
74#define ctf_ipc_lkup_l4proto(ci, iph, l4p)	(CTF_ENAB(ci) && (ci)->fn.ipc_lkup_l4proto? \
75	(ci)->fn.ipc_lkup_l4proto((uint8 *)iph, l4p) : NULL)
76#else
77#define ctf_ipc_lkup_l4proto(ci, iph, l4p)	(NULL)
78#endif /* CTF_IPV6 */
79#define ctf_ipc_release(ci, i)	do { if (CTF_ENAB(ci)) (ci)->fn.ipc_release(ci, i); } while (0)
80#define ctf_dev_register(ci, d, b)	\
81	(CTF_ENAB(ci) ? (ci)->fn.dev_register(ci, d, b) : BCME_OK)
82#define ctf_dev_vlan_add(ci, d, vid, vd)	\
83	(CTF_ENAB(ci) ? (ci)->fn.dev_vlan_add(ci, d, vid, vd) : BCME_OK)
84#define ctf_dev_vlan_delete(ci, d, vid)	\
85	(CTF_ENAB(ci) ? (ci)->fn.dev_vlan_delete(ci, d, vid) : BCME_OK)
86#define ctf_detach(ci)			if (CTF_ENAB(ci)) (ci)->fn.detach(ci)
87#define ctf_dump(ci, b)			if (CTF_ENAB(ci)) (ci)->fn.dump(ci, b)
88#define ctf_cfg_req_process(ci, c)	if (CTF_ENAB(ci)) (ci)->fn.cfg_req_process(ci, c)
89#define ctf_dev_unregister(ci, d)	if (CTF_ENAB(ci)) (ci)->fn.dev_unregister(ci, d)
90
91#define CTFCNTINCR(s) ((s)++)
92#define CTFCNTADD(s, c) ((s) += (c))
93
94#define PPPOE_ETYPE_OFFSET	12
95#define PPPOE_VER_OFFSET	14
96#define PPPOE_SESID_OFFSET	16
97#define PPPOE_LEN_OFFSET	18
98
99#define PPPOE_HLEN		20
100
101#define PPPOE_PROT_PPP		0x0021
102
103
104typedef struct ctf_pub	ctf_t;
105typedef struct ctf_brc	ctf_brc_t;
106typedef struct ctf_ipc	ctf_ipc_t;
107typedef struct ctf_conn_tuple	ctf_conn_tuple_t;
108typedef struct ctf_brc_hot ctf_brc_hot_t;
109
110typedef void (*ctf_detach_cb_t)(ctf_t *ci, void *arg);
111typedef ctf_t * (*ctf_attach_t)(osl_t *osh, uint8 *name, uint32 *msg_level,
112                                ctf_detach_cb_t cb, void *arg);
113typedef void (*ctf_detach_t)(ctf_t *ci);
114typedef int32 (*ctf_forward_t)(ctf_t *ci, void *p, void *rxifp);
115typedef bool (*ctf_isenabled_t)(ctf_t *ci, void *dev);
116typedef bool (*ctf_isbridge_t)(ctf_t *ci, void *dev);
117typedef int32 (*ctf_brc_add_t)(ctf_t *ci, ctf_brc_t *brc);
118typedef int32 (*ctf_brc_delete_t)(ctf_t *ci, uint8 *ea);
119typedef int32 (*ctf_brc_update_t)(ctf_t *ci, ctf_brc_t *brc);
120typedef ctf_brc_t * (*ctf_brc_lkup_t)(ctf_t *ci, uint8 *da);
121typedef void (*ctf_brc_release_t)(ctf_t *ci, ctf_brc_t *brc);
122typedef int32 (*ctf_ipc_add_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6);
123typedef int32 (*ctf_ipc_delete_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6);
124typedef int32 (*ctf_ipc_count_get_t)(ctf_t *ci);
125typedef int32 (*ctf_ipc_delete_multi_t)(ctf_t *ci, ctf_ipc_t *ipc,
126                                        ctf_ipc_t *ipcm, bool v6);
127typedef int32 (*ctf_ipc_delete_range_t)(ctf_t *ci, ctf_ipc_t *start,
128                                        ctf_ipc_t *end, bool v6);
129typedef int32 (*ctf_ipc_action_t)(ctf_t *ci, ctf_ipc_t *start,
130                                  ctf_ipc_t *end, uint32 action_mask, bool v6);
131typedef ctf_ipc_t * (*ctf_ipc_lkup_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6);
132typedef	uint8 * (*ctf_ipc_lkup_l4proto_t)(uint8 *iph, uint8 *proto_num);
133typedef void (*ctf_ipc_release_t)(ctf_t *ci, ctf_ipc_t *ipc);
134typedef int32 (*ctf_enable_t)(ctf_t *ci, void *dev, bool enable, ctf_brc_hot_t **brc_hot);
135typedef int32 (*ctf_dev_register_t)(ctf_t *ci, void *dev, bool br);
136typedef void (*ctf_dev_unregister_t)(ctf_t *ci, void *dev);
137typedef int32 (*ctf_dev_vlan_add_t)(ctf_t *ci, void *dev, uint16 vid, void *vldev);
138typedef int32 (*ctf_dev_vlan_delete_t)(ctf_t *ci, void *dev, uint16 vid);
139typedef void (*ctf_dump_t)(ctf_t *ci, struct bcmstrbuf *b);
140typedef void (*ctf_cfg_req_process_t)(ctf_t *ci, void *arg);
141
142struct ctf_brc_hot {
143	struct ether_addr	ea;	/* Dest address */
144	ctf_brc_t		*brcp;	/* BRC entry corresp to dest mac */
145};
146
147typedef struct ctf_fn {
148	ctf_detach_t		detach;
149	ctf_forward_t		forward;
150	ctf_isenabled_t		isenabled;
151	ctf_isbridge_t		isbridge;
152	ctf_brc_add_t		brc_add;
153	ctf_brc_delete_t	brc_delete;
154	ctf_brc_update_t	brc_update;
155	ctf_brc_lkup_t		brc_lkup;
156	ctf_brc_release_t	brc_release;
157	ctf_ipc_add_t		ipc_add;
158	ctf_ipc_delete_t	ipc_delete;
159	ctf_ipc_count_get_t	ipc_count_get;
160	ctf_ipc_delete_multi_t	ipc_delete_multi;
161	ctf_ipc_delete_range_t	ipc_delete_range;
162	ctf_ipc_action_t	ipc_action;
163	ctf_ipc_lkup_t		ipc_lkup;
164	ctf_ipc_lkup_l4proto_t	ipc_lkup_l4proto;
165	ctf_ipc_release_t	ipc_release;
166	ctf_enable_t		enable;
167	ctf_dev_register_t	dev_register;
168	ctf_dev_unregister_t	dev_unregister;
169	ctf_detach_cb_t		detach_cb;
170	void			*detach_cb_arg;
171	ctf_dev_vlan_add_t	dev_vlan_add;
172	ctf_dev_vlan_delete_t	dev_vlan_delete;
173	ctf_dump_t		dump;
174	ctf_cfg_req_process_t	cfg_req_process;
175} ctf_fn_t;
176
177struct ctf_pub {
178	bool			_ctf;		/* Global CTF enable/disable */
179	ctf_fn_t		fn;		/* Exported functions */
180	void			*nl_sk;		/* Netlink socket */
181	uint32			ipc_suspend;	/* Global IPC suspend flags */
182};
183
184struct ctf_mark;	/* Connection Mark */
185
186struct ctf_brc {
187	struct	ctf_brc		*next;		/* Pointer to brc entry */
188	struct	ether_addr	dhost;		/* MAC addr of host */
189	uint16			vid;		/* VLAN id to use on txif */
190	void			*txifp;		/* Interface connected to host */
191	uint32			action;		/* Tag or untag the frames */
192	uint32			live;		/* Counter used to expire the entry */
193	uint32			hits;		/* Num frames matching brc entry */
194	uint64			*bytecnt_ptr;	/* Pointer to the byte counter */
195};
196
197#ifdef CTF_IPV6
198#define IPADDR_U32_SZ		(IPV6_ADDR_LEN / sizeof(uint32))
199#else
200#define IPADDR_U32_SZ		1
201#endif
202
203struct ctf_conn_tuple {
204	uint32	sip[IPADDR_U32_SZ], dip[IPADDR_U32_SZ];
205	uint16	sp, dp;
206	uint8	proto;
207};
208
209typedef struct ctf_nat {
210	uint32	ip;
211	uint16	port;
212} ctf_nat_t;
213
214struct ctf_ipc {
215	struct	ctf_ipc		*next;		/* Pointer to ipc entry */
216	ctf_conn_tuple_t	tuple;		/* Tuple to uniquely id the flow */
217	uint16			vid;		/* VLAN id to use on txif */
218	struct	ether_addr	dhost;		/* Destination MAC address */
219	struct	ether_addr	shost;		/* Source MAC address */
220	void			*txif;		/* Target interface to send */
221	uint32			action;		/* NAT and/or VLAN actions */
222	ctf_brc_t		*brcp;		/* BRC entry corresp to source mac */
223	uint32			live;		/* Counter used to expire the entry */
224	struct	ctf_nat		nat;		/* Manip data for SNAT, DNAT */
225	struct	ether_addr	sa;		/* MAC address of sender */
226	uint8			tos;		/* IPv4 tos or IPv6 traff class excl ECN */
227	uint16			pppoe_sid;	/* PPPOE session to use */
228	void			*ppp_ifp;	/* PPP interface handle */
229	uint32			hits;		/* Num frames matching ipc entry */
230	uint64			*bytecnt_ptr;	/* Pointer to the byte counter */
231	struct	ctf_mark	mark;		/* Mark value to use for the connection */
232};
233
234extern ctf_t *ctf_kattach(osl_t *osh, uint8 *name);
235extern void ctf_kdetach(ctf_t *kci);
236extern ctf_attach_t ctf_attach_fn;
237extern ctf_t *_ctf_attach(osl_t *osh, uint8 *name, uint32 *msg_level,
238                          ctf_detach_cb_t cb, void *arg);
239extern ctf_t *kcih;
240
241/* Hot bridge cache lkup */
242#define MAXBRCHOT		4
243#define MAXBRCHOTIF		4
244#define CTF_BRC_HOT_HASH(da) 	((((uint8 *)da)[4] ^ ((uint8 *)da)[5]) & (MAXBRCHOT - 1))
245#define CTF_HOTBRC_CMP(hbrc, da, rxifp) \
246({ \
247	ctf_brc_hot_t *bh = (hbrc) + CTF_BRC_HOT_HASH(da); \
248	((eacmp((bh)->ea.octet, (da)) == 0) && (bh->brcp->txifp != (rxifp))); \
249})
250
251/* Header prep for packets matching hot bridge cache entry */
252#define CTF_HOTBRC_L2HDR_PREP(osh, hbrc, prio, data, p) \
253do { \
254	uint8 *l2h; \
255	ctf_brc_hot_t *bh = (hbrc) + CTF_BRC_HOT_HASH(data); \
256	ASSERT(*(uint16 *)((data) + VLAN_TPID_OFFSET) == HTON16(ETHER_TYPE_8021Q)); \
257	if (bh->brcp->action & CTF_ACTION_UNTAG) { \
258		/* Remove vlan header */ \
259		l2h = PKTPULL((osh), (p), VLAN_TAG_LEN); \
260		ether_rcopy(l2h - VLAN_TAG_LEN + ETHER_ADDR_LEN, \
261		            l2h + ETHER_ADDR_LEN); \
262		ether_rcopy(l2h - VLAN_TAG_LEN, l2h); \
263	} else { \
264		/* Update vlan header */ \
265		l2h = (data); \
266		*(uint16 *)(l2h + VLAN_TCI_OFFSET) = \
267		            HTON16((prio) << VLAN_PRI_SHIFT | bh->brcp->vid); \
268	} \
269} while (0)
270
271
272#endif /* _HNDCTF_H_ */
273