1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
|
/* $OpenBSD: if_trunk.h,v 1.11 2007/01/31 06:20:19 reyk Exp $ */
/*
* Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
*/
#ifndef _NET_LAGG_H
#define _NET_LAGG_H
/*
* Global definitions
*/
#define LAGG_MAX_PORTS 32 /* logically */
#define LAGG_MAX_NAMESIZE 32 /* name of a protocol */
#define LAGG_MAX_STACKING 4 /* maximum number of stacked laggs */
/* Lagg flags */
#define LAGG_F_HASHL2 0x00000001 /* hash layer 2 */
#define LAGG_F_HASHL3 0x00000002 /* hash layer 3 */
#define LAGG_F_HASHL4 0x00000004 /* hash layer 4 */
#define LAGG_F_HASHMASK 0x00000007
/* Port flags */
#define LAGG_PORT_SLAVE 0x00000000 /* normal enslaved port */
#define LAGG_PORT_MASTER 0x00000001 /* primary port */
#define LAGG_PORT_STACK 0x00000002 /* stacked lagg port */
#define LAGG_PORT_ACTIVE 0x00000004 /* port is active */
#define LAGG_PORT_COLLECTING 0x00000008 /* port is receiving frames */
#define LAGG_PORT_DISTRIBUTING 0x00000010 /* port is sending frames */
#define LAGG_PORT_DISABLED 0x00000020 /* port is disabled */
#define LAGG_PORT_BITS "\20\01MASTER\02STACK\03ACTIVE\04COLLECTING" \
"\05DISTRIBUTING\06DISABLED"
/* Supported lagg PROTOs */
typedef enum {
LAGG_PROTO_NONE = 0, /* no lagg protocol defined */
LAGG_PROTO_ROUNDROBIN, /* simple round robin */
LAGG_PROTO_FAILOVER, /* active failover */
LAGG_PROTO_LOADBALANCE, /* loadbalance */
LAGG_PROTO_LACP, /* 802.3ad lacp */
LAGG_PROTO_ETHERCHANNEL,/* Cisco FEC */
LAGG_PROTO_BROADCAST, /* broadcast */
LAGG_PROTO_MAX,
} lagg_proto;
struct lagg_protos {
const char *lpr_name;
lagg_proto lpr_proto;
};
#define LAGG_PROTO_DEFAULT LAGG_PROTO_FAILOVER
#define LAGG_PROTOS { \
{ "failover", LAGG_PROTO_FAILOVER }, \
{ "fec", LAGG_PROTO_ETHERCHANNEL }, \
{ "lacp", LAGG_PROTO_LACP }, \
{ "loadbalance", LAGG_PROTO_LOADBALANCE }, \
{ "roundrobin", LAGG_PROTO_ROUNDROBIN }, \
{ "broadcast", LAGG_PROTO_BROADCAST }, \
{ "none", LAGG_PROTO_NONE }, \
{ "default", LAGG_PROTO_DEFAULT } \
}
/*
* lagg ioctls.
*/
/*
* LACP current operational parameters structure.
*/
struct lacp_opreq {
uint16_t actor_prio;
uint8_t actor_mac[ETHER_ADDR_LEN];
uint16_t actor_key;
uint16_t actor_portprio;
uint16_t actor_portno;
uint8_t actor_state;
uint16_t partner_prio;
uint8_t partner_mac[ETHER_ADDR_LEN];
uint16_t partner_key;
uint16_t partner_portprio;
uint16_t partner_portno;
uint8_t partner_state;
};
/* lagg port settings */
struct lagg_reqport {
char rp_ifname[IFNAMSIZ]; /* name of the lagg */
char rp_portname[IFNAMSIZ]; /* name of the port */
u_int32_t rp_prio; /* port priority */
u_int32_t rp_flags; /* port flags */
union {
struct lacp_opreq rpsc_lacp;
} rp_psc;
#define rp_lacpreq rp_psc.rpsc_lacp
};
#define SIOCGLAGGPORT _IOWR('i', 140, struct lagg_reqport)
#define SIOCSLAGGPORT _IOW('i', 141, struct lagg_reqport)
#define SIOCSLAGGDELPORT _IOW('i', 142, struct lagg_reqport)
/* lagg, ports and options */
struct lagg_reqall {
char ra_ifname[IFNAMSIZ]; /* name of the lagg */
u_int ra_proto; /* lagg protocol */
size_t ra_size; /* size of buffer */
struct lagg_reqport *ra_port; /* allocated buffer */
int ra_ports; /* total port count */
union {
struct lacp_opreq rpsc_lacp;
} ra_psc;
#define ra_lacpreq ra_psc.rpsc_lacp
};
#define SIOCGLAGG _IOWR('i', 143, struct lagg_reqall)
#define SIOCSLAGG _IOW('i', 144, struct lagg_reqall)
struct lagg_reqflags {
char rf_ifname[IFNAMSIZ]; /* name of the lagg */
uint32_t rf_flags; /* lagg protocol */
};
#define SIOCGLAGGFLAGS _IOWR('i', 145, struct lagg_reqflags)
#define SIOCSLAGGHASH _IOW('i', 146, struct lagg_reqflags)
struct lagg_reqopts {
char ro_ifname[IFNAMSIZ]; /* name of the lagg */
int ro_opts; /* Option bitmap */
#define LAGG_OPT_NONE 0x00
#define LAGG_OPT_USE_FLOWID 0x01 /* enable use of flowid */
/* Pseudo flags which are used in ro_opts but not stored into sc_opts. */
#define LAGG_OPT_FLOWIDSHIFT 0x02 /* set flowid shift */
#define LAGG_OPT_FLOWIDSHIFT_MASK 0x1f /* flowid is uint32_t */
#define LAGG_OPT_LACP_STRICT 0x10 /* LACP strict mode */
#define LAGG_OPT_LACP_TXTEST 0x20 /* LACP debug: txtest */
#define LAGG_OPT_LACP_RXTEST 0x40 /* LACP debug: rxtest */
u_int ro_count; /* number of ports */
u_int ro_active; /* active port count */
u_int ro_flapping; /* number of flapping */
int ro_flowid_shift; /* shift the flowid */
};
#define SIOCGLAGGOPTS _IOWR('i', 152, struct lagg_reqopts)
#define SIOCSLAGGOPTS _IOW('i', 153, struct lagg_reqopts)
#define LAGG_OPT_BITS "\020\001USE_FLOWID\005LACP_STRICT" \
"\006LACP_TXTEST\007LACP_RXTEST"
#ifdef _KERNEL
/*
* Internal kernel part
*/
#define LAGG_PORTACTIVE(_tp) ( \
((_tp)->lp_ifp->if_link_state == LINK_STATE_UP) && \
((_tp)->lp_ifp->if_flags & IFF_UP) \
)
struct lagg_ifreq {
union {
struct ifreq ifreq;
struct {
char ifr_name[IFNAMSIZ];
struct sockaddr_storage ifr_ss;
} ifreq_storage;
} ifreq;
};
#define sc_ifflags sc_ifp->if_flags /* flags */
#define sc_ifname sc_ifp->if_xname /* name */
#define sc_capabilities sc_ifp->if_capabilities /* capabilities */
#define IFCAP_LAGG_MASK 0xffff0000 /* private capabilities */
#define IFCAP_LAGG_FULLDUPLEX 0x00010000 /* full duplex with >1 ports */
/* Private data used by the loadbalancing protocol */
struct lagg_lb {
u_int32_t lb_key;
struct lagg_port *lb_ports[LAGG_MAX_PORTS];
};
struct lagg_mc {
struct sockaddr_dl mc_addr;
struct ifmultiaddr *mc_ifma;
SLIST_ENTRY(lagg_mc) mc_entries;
};
/* List of interfaces to have the MAC address modified */
struct lagg_llq {
struct ifnet *llq_ifp;
uint8_t llq_lladdr[ETHER_ADDR_LEN];
uint8_t llq_primary;
SLIST_ENTRY(lagg_llq) llq_entries;
};
struct lagg_counters {
uint64_t val[IFCOUNTERS];
};
struct lagg_softc {
struct ifnet *sc_ifp; /* virtual interface */
struct rmlock sc_mtx;
int sc_proto; /* lagg protocol */
u_int sc_count; /* number of ports */
u_int sc_active; /* active port count */
u_int sc_flapping; /* number of flapping
* events */
struct lagg_port *sc_primary; /* primary port */
struct ifmedia sc_media; /* media config */
void *sc_psc; /* protocol data */
uint32_t sc_seq; /* sequence counter */
uint32_t sc_flags;
SLIST_HEAD(__tplhd, lagg_port) sc_ports; /* list of interfaces */
SLIST_ENTRY(lagg_softc) sc_entries;
struct task sc_lladdr_task;
SLIST_HEAD(__llqhd, lagg_llq) sc_llq_head; /* interfaces to program
the lladdr on */
eventhandler_tag vlan_attach;
eventhandler_tag vlan_detach;
struct callout sc_callout;
u_int sc_opts;
int flowid_shift; /* shift the flowid */
struct lagg_counters detached_counters; /* detached ports sum */
};
struct lagg_port {
struct ifnet *lp_ifp; /* physical interface */
struct lagg_softc *lp_softc; /* parent lagg */
uint8_t lp_lladdr[ETHER_ADDR_LEN];
u_char lp_iftype; /* interface type */
uint32_t lp_prio; /* port priority */
uint32_t lp_flags; /* port flags */
int lp_ifflags; /* saved ifp flags */
void *lh_cookie; /* if state hook */
void *lp_psc; /* protocol data */
int lp_detaching; /* ifnet is detaching */
SLIST_HEAD(__mclhd, lagg_mc) lp_mc_head; /* multicast addresses */
/* Redirected callbacks */
int (*lp_ioctl)(struct ifnet *, u_long, caddr_t);
int (*lp_output)(struct ifnet *, struct mbuf *,
const struct sockaddr *, struct route *);
struct lagg_counters port_counters; /* ifp counters copy */
SLIST_ENTRY(lagg_port) lp_entries;
};
#define LAGG_LOCK_INIT(_sc) rm_init(&(_sc)->sc_mtx, "if_lagg rmlock")
#define LAGG_LOCK_DESTROY(_sc) rm_destroy(&(_sc)->sc_mtx)
#define LAGG_RLOCK(_sc, _p) rm_rlock(&(_sc)->sc_mtx, (_p))
#define LAGG_WLOCK(_sc) rm_wlock(&(_sc)->sc_mtx)
#define LAGG_RUNLOCK(_sc, _p) rm_runlock(&(_sc)->sc_mtx, (_p))
#define LAGG_WUNLOCK(_sc) rm_wunlock(&(_sc)->sc_mtx)
#define LAGG_RLOCK_ASSERT(_sc) rm_assert(&(_sc)->sc_mtx, RA_RLOCKED)
#define LAGG_WLOCK_ASSERT(_sc) rm_assert(&(_sc)->sc_mtx, RA_WLOCKED)
extern struct mbuf *(*lagg_input_p)(struct ifnet *, struct mbuf *);
extern void (*lagg_linkstate_p)(struct ifnet *, int );
int lagg_enqueue(struct ifnet *, struct mbuf *);
uint32_t lagg_hashmbuf(struct lagg_softc *, struct mbuf *, uint32_t);
SYSCTL_DECL(_net_link_lagg);
#endif /* _KERNEL */
#endif /* _NET_LAGG_H */
|