|
@@ -1,406 +0,0 @@
|
1
|
|
-/* Copyright 2004 Linux Networx */
|
2
|
|
-#ifdef PROTO_LACP
|
3
|
|
-#if 0
|
4
|
|
-#include "nic.h"
|
5
|
|
-#include "timer.h"
|
6
|
|
-#endif
|
7
|
|
-
|
8
|
|
-#define LACP_DEBUG 0
|
9
|
|
-
|
10
|
|
-/* Structure definitions originally taken from the linux bond_3ad driver */
|
11
|
|
-
|
12
|
|
-#define SLOW_DST_MAC "\x01\x80\xc2\x00\x00\x02"
|
13
|
|
-static const char slow_dest[] = SLOW_DST_MAC;
|
14
|
|
-
|
15
|
|
-
|
16
|
|
-#define SLOW_SUBTYPE_LACP 1
|
17
|
|
-#define SLOW_SUBTYPE_MARKER 2
|
18
|
|
-
|
19
|
|
-struct slow_header {
|
20
|
|
- uint8_t subtype;
|
21
|
|
-};
|
22
|
|
-
|
23
|
|
-struct lacp_info {
|
24
|
|
- uint16_t system_priority;
|
25
|
|
- uint8_t system[ETH_ALEN];
|
26
|
|
- uint16_t key;
|
27
|
|
- uint16_t port_priority;
|
28
|
|
- uint16_t port;
|
29
|
|
- uint8_t state;
|
30
|
|
- uint8_t reserved[3];
|
31
|
|
-} PACKED;
|
32
|
|
-
|
33
|
|
-#define LACP_CMP_LEN (2 + 6 + 2 + 2 + 2)
|
34
|
|
-#define LACP_CP_LEN (2 + 6 + 2 + 2 + 2 + 1)
|
35
|
|
-
|
36
|
|
-/* Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard) */
|
37
|
|
-struct slow_lacp {
|
38
|
|
- uint8_t subtype; /* = LACP(= 0x01) */
|
39
|
|
- uint8_t version_number;
|
40
|
|
- uint8_t tlv_type_actor_info; /* = actor information(type/length/value) */
|
41
|
|
-#define LACP_TLV_TERMINATOR 0
|
42
|
|
-#define LACP_TLV_ACTOR 1
|
43
|
|
-#define LACP_TLV_PARTNER 2
|
44
|
|
-#define LACP_TLV_COLLECTOR 3
|
45
|
|
- uint8_t actor_information_length; /* = 20 */
|
46
|
|
- struct lacp_info actor;
|
47
|
|
- uint8_t tlv_type_partner_info; /* = partner information */
|
48
|
|
- uint8_t partner_information_length; /* = 20 */
|
49
|
|
- struct lacp_info partner;
|
50
|
|
- uint8_t tlv_type_collector_info; /* = collector information */
|
51
|
|
- uint8_t collector_information_length; /* = 16 */
|
52
|
|
- uint16_t collector_max_delay;
|
53
|
|
- uint8_t reserved_12[12];
|
54
|
|
- uint8_t tlv_type_terminator; /* = terminator */
|
55
|
|
- uint8_t terminator_length; /* = 0 */
|
56
|
|
- uint8_t reserved_50[50]; /* = 0 */
|
57
|
|
-} PACKED;
|
58
|
|
-
|
59
|
|
-/* Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard) */
|
60
|
|
-struct slow_marker {
|
61
|
|
- uint8_t subtype; /* = 0x02 (marker PDU) */
|
62
|
|
- uint8_t version_number; /* = 0x01 */
|
63
|
|
- uint8_t tlv_type;
|
64
|
|
-#define MARKER_TLV_TERMINATOR 0 /* marker terminator */
|
65
|
|
-#define MARKER_TLV_INFO 1 /* marker information */
|
66
|
|
-#define MARKER_TLV_RESPONSE 2 /* marker response information */
|
67
|
|
- uint8_t marker_length; /* = 0x16 */
|
68
|
|
- uint16_t requester_port; /* The number assigned to the port by the requester */
|
69
|
|
- uint8_t requester_system[ETH_ALEN]; /* The requester's system id */
|
70
|
|
- uint32_t requester_transaction_id; /* The transaction id allocated by the requester, */
|
71
|
|
- uint16_t pad; /* = 0 */
|
72
|
|
- uint8_t tlv_type_terminator; /* = 0x00 */
|
73
|
|
- uint8_t terminator_length; /* = 0x00 */
|
74
|
|
- uint8_t reserved_90[90]; /* = 0 */
|
75
|
|
-} PACKED;
|
76
|
|
-
|
77
|
|
-union slow_union {
|
78
|
|
- struct slow_header header;
|
79
|
|
- struct slow_lacp lacp;
|
80
|
|
- struct slow_marker marker;
|
81
|
|
-};
|
82
|
|
-
|
83
|
|
-#define FAST_PERIODIC_TIME (1*TICKS_PER_SEC)
|
84
|
|
-#define SLOW_PERIODIC_TIME (30*TICKS_PER_SEC)
|
85
|
|
-#define SHORT_TIMEOUT_TIME (3*FAST_PERIODIC_TIME)
|
86
|
|
-#define LONG_TIMEOUT_TIME (3*SLOW_PERIODIC_TIME)
|
87
|
|
-#define CHURN_DETECTION_TIME (60*TICKS_PER_SEC)
|
88
|
|
-#define AGGREGATE_WAIT_TIME (2*TICKS_PER_SEC)
|
89
|
|
-
|
90
|
|
-#define LACP_ACTIVITY (1 << 0)
|
91
|
|
-#define LACP_TIMEOUT (1 << 1)
|
92
|
|
-#define LACP_AGGREGATION (1 << 2)
|
93
|
|
-#define LACP_SYNCHRONIZATION (1 << 3)
|
94
|
|
-#define LACP_COLLECTING (1 << 4)
|
95
|
|
-#define LACP_DISTRIBUTING (1 << 5)
|
96
|
|
-#define LACP_DEFAULTED (1 << 6)
|
97
|
|
-#define LACP_EXPIRED (1 << 7)
|
98
|
|
-
|
99
|
|
-#define UNSELECTED 0
|
100
|
|
-#define STANDBY 1
|
101
|
|
-#define SELECTED 2
|
102
|
|
-
|
103
|
|
-
|
104
|
|
-struct lacp_state {
|
105
|
|
- struct slow_lacp pkt;
|
106
|
|
- unsigned long current_while_timer; /* Time when the LACP information expires */
|
107
|
|
- unsigned long periodic_timer; /* Time when I need to send my partner an update */
|
108
|
|
-};
|
109
|
|
-
|
110
|
|
-static struct lacp_state lacp;
|
111
|
|
-
|
112
|
|
-
|
113
|
|
-#if LACP_DEBUG > 0
|
114
|
|
-static void print_lacp_state(uint8_t state)
|
115
|
|
-{
|
116
|
|
- printf("%hhx", state);
|
117
|
|
- if (state & LACP_ACTIVITY) {
|
118
|
|
- printf(" Activity");
|
119
|
|
- }
|
120
|
|
- if (state & LACP_TIMEOUT) {
|
121
|
|
- printf(" Timeout");
|
122
|
|
- }
|
123
|
|
- if (state & LACP_AGGREGATION) {
|
124
|
|
- printf(" Aggregation");
|
125
|
|
- }
|
126
|
|
- if (state & LACP_SYNCHRONIZATION) {
|
127
|
|
- printf(" Syncronization");
|
128
|
|
- }
|
129
|
|
- if (state & LACP_COLLECTING) {
|
130
|
|
- printf(" Collecting");
|
131
|
|
- }
|
132
|
|
- if (state & LACP_DISTRIBUTING) {
|
133
|
|
- printf(" Distributing");
|
134
|
|
- }
|
135
|
|
- if (state & LACP_DEFAULTED) {
|
136
|
|
- printf(" Defaulted");
|
137
|
|
- }
|
138
|
|
- if (state & LACP_EXPIRED) {
|
139
|
|
- printf(" Expired");
|
140
|
|
- }
|
141
|
|
- printf("\n");
|
142
|
|
-}
|
143
|
|
-
|
144
|
|
-static inline void print_lacpdu(struct slow_lacp *pkt)
|
145
|
|
-{
|
146
|
|
- printf("subtype version: %hhx %hhx\n",
|
147
|
|
- pkt->subtype, pkt->version_number);
|
148
|
|
- printf("actor_tlv %hhx", pkt->tlv_type_actor_info);
|
149
|
|
- printf(" len: %hhx (\n", pkt->actor_information_length);
|
150
|
|
- printf(" sys_pri: %hx", ntohs(pkt->actor.system_priority));
|
151
|
|
- printf(" mac: %!", pkt->actor.system);
|
152
|
|
- printf(" key: %hx", ntohs(pkt->actor.key));
|
153
|
|
- printf(" port_pri: %hx", ntohs(pkt->actor.port_priority));
|
154
|
|
- printf(" port: %hx\n", ntohs(pkt->actor.port));
|
155
|
|
- printf(" state: ");
|
156
|
|
- print_lacp_state(pkt->actor.state);
|
157
|
|
-#if LACP_DEBUG > 1
|
158
|
|
- printf(" reserved: %hhx %hhx %hhx\n",
|
159
|
|
- pkt->actor.reserved[0], pkt->actor.reserved[1], pkt->actor.reserved[2]);
|
160
|
|
-#endif
|
161
|
|
- printf(")\n");
|
162
|
|
- printf("partner_tlv: %hhx", pkt->tlv_type_partner_info);
|
163
|
|
- printf(" len: %hhx (\n", pkt->partner_information_length);
|
164
|
|
- printf(" sys_pri: %hx", ntohs(pkt->partner.system_priority));
|
165
|
|
- printf(" mac: %!", pkt->partner.system);
|
166
|
|
- printf(" key: %hx", ntohs(pkt->partner.key));
|
167
|
|
- printf(" port_pri: %hx", ntohs(pkt->partner.port_priority));
|
168
|
|
- printf(" port: %hx\n", ntohs(pkt->partner.port));
|
169
|
|
- printf(" state: ");
|
170
|
|
- print_lacp_state(pkt->partner.state);
|
171
|
|
-#if LACP_DEBUG > 1
|
172
|
|
- printf(" reserved: %hhx %hhx %hhx\n",
|
173
|
|
- pkt->partner.reserved[0], pkt->partner.reserved[1], pkt->partner.reserved[2]);
|
174
|
|
-#endif
|
175
|
|
- printf(")\n");
|
176
|
|
- printf("collector_tlv: %hhx ", pkt->tlv_type_collector_info);
|
177
|
|
- printf(" len: %hhx (", pkt->collector_information_length);
|
178
|
|
- printf(" max_delay: %hx", ntohs(pkt->collector_max_delay));
|
179
|
|
-#if LACP_DEBUG > 1
|
180
|
|
- printf("reserved_12: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
|
181
|
|
- pkt->reserved_12[0], pkt->reserved_12[1], pkt->reserved_12[2],
|
182
|
|
- pkt->reserved_12[3], pkt->reserved_12[4], pkt->reserved_12[5],
|
183
|
|
- pkt->reserved_12[6], pkt->reserved_12[7], pkt->reserved_12[8],
|
184
|
|
- pkt->reserved_12[9], pkt->reserved_12[10], pkt->reserved_12[11]);
|
185
|
|
-#endif
|
186
|
|
- printf(" )\n");
|
187
|
|
- printf("terminator_tlv: %hhx", pkt->tlv_type_terminator);
|
188
|
|
- printf(" len: %hhx ()\n", pkt->terminator_length);
|
189
|
|
-}
|
190
|
|
-
|
191
|
|
-static inline unsigned long lacp_timer_val(unsigned long now, unsigned long when)
|
192
|
|
-{
|
193
|
|
- return when?(when - now)/TICKS_PER_SEC : 0;
|
194
|
|
-}
|
195
|
|
-static void print_lacp(const char *which, struct slow_lacp *pkt, unsigned long now)
|
196
|
|
-{
|
197
|
|
- printf("%s\n", which);
|
198
|
|
- print_lacpdu(pkt);
|
199
|
|
- printf("timers: c %ds p %ds\n",
|
200
|
|
- lacp_timer_val(now, lacp.current_while_timer),
|
201
|
|
- lacp_timer_val(now, lacp.periodic_timer)
|
202
|
|
- );
|
203
|
|
- printf("\n");
|
204
|
|
-}
|
205
|
|
-#else /* LACP_DEBUG */
|
206
|
|
-#define print_lacp(which, pkt, now) do {} while(0)
|
207
|
|
-#endif /* LACP_DEBUG */
|
208
|
|
-
|
209
|
|
-static void lacp_init_state(const uint8_t *mac)
|
210
|
|
-{
|
211
|
|
- memset(&lacp, 0, sizeof(lacp));
|
212
|
|
-
|
213
|
|
- /* Initialize the packet constants */
|
214
|
|
- lacp.pkt.subtype = 1;
|
215
|
|
- lacp.pkt.version_number = 1;
|
216
|
|
-
|
217
|
|
-
|
218
|
|
- /* The default state of my interface */
|
219
|
|
- lacp.pkt.tlv_type_actor_info = LACP_TLV_ACTOR;
|
220
|
|
- lacp.pkt.actor_information_length = 0x14;
|
221
|
|
- lacp.pkt.actor.system_priority = htons(1);
|
222
|
|
- memcpy(lacp.pkt.actor.system, mac, ETH_ALEN);
|
223
|
|
- lacp.pkt.actor.key = htons(1);
|
224
|
|
- lacp.pkt.actor.port = htons(1);
|
225
|
|
- lacp.pkt.actor.port_priority = htons(1);
|
226
|
|
- lacp.pkt.actor.state =
|
227
|
|
- LACP_SYNCHRONIZATION |
|
228
|
|
- LACP_COLLECTING |
|
229
|
|
- LACP_DISTRIBUTING |
|
230
|
|
- LACP_DEFAULTED;
|
231
|
|
-
|
232
|
|
- /* Set my partner defaults */
|
233
|
|
- lacp.pkt.tlv_type_partner_info = LACP_TLV_PARTNER;
|
234
|
|
- lacp.pkt.partner_information_length = 0x14;
|
235
|
|
- lacp.pkt.partner.system_priority = htons(1);
|
236
|
|
- /* memset(lacp.pkt.parnter_system, 0, ETH_ALEN); */
|
237
|
|
- lacp.pkt.partner.key = htons(1);
|
238
|
|
- lacp.pkt.partner.port = htons(1);
|
239
|
|
- lacp.pkt.partner.port_priority = htons(1);
|
240
|
|
- lacp.pkt.partner.state =
|
241
|
|
- LACP_ACTIVITY |
|
242
|
|
- LACP_SYNCHRONIZATION |
|
243
|
|
- LACP_COLLECTING |
|
244
|
|
- LACP_DISTRIBUTING |
|
245
|
|
- LACP_DEFAULTED;
|
246
|
|
-
|
247
|
|
- lacp.pkt.tlv_type_collector_info = LACP_TLV_COLLECTOR;
|
248
|
|
- lacp.pkt.collector_information_length = 0x10;
|
249
|
|
- lacp.pkt.collector_max_delay = htons(0x8000); /* ???? */
|
250
|
|
-
|
251
|
|
- lacp.pkt.tlv_type_terminator = LACP_TLV_TERMINATOR;
|
252
|
|
- lacp.pkt.terminator_length = 0;
|
253
|
|
-}
|
254
|
|
-
|
255
|
|
-#define LACP_NTT_MASK (LACP_ACTIVITY | LACP_TIMEOUT | \
|
256
|
|
- LACP_SYNCHRONIZATION | LACP_AGGREGATION)
|
257
|
|
-
|
258
|
|
-static inline int lacp_update_ntt(struct slow_lacp *pkt)
|
259
|
|
-{
|
260
|
|
- int ntt = 0;
|
261
|
|
- if ((memcmp(&pkt->partner, &lacp.pkt.actor, LACP_CMP_LEN) != 0) ||
|
262
|
|
- ((pkt->partner.state & LACP_NTT_MASK) !=
|
263
|
|
- (lacp.pkt.actor.state & LACP_NTT_MASK)))
|
264
|
|
- {
|
265
|
|
- ntt = 1;
|
266
|
|
- }
|
267
|
|
- return ntt;
|
268
|
|
-}
|
269
|
|
-
|
270
|
|
-static inline void lacp_record_pdu(struct slow_lacp *pkt)
|
271
|
|
-{
|
272
|
|
- memcpy(&lacp.pkt.partner, &pkt->actor, LACP_CP_LEN);
|
273
|
|
-
|
274
|
|
- lacp.pkt.actor.state &= ~LACP_DEFAULTED;
|
275
|
|
- lacp.pkt.partner.state &= ~LACP_SYNCHRONIZATION;
|
276
|
|
- if ((memcmp(&pkt->partner, &lacp.pkt.actor, LACP_CMP_LEN) == 0) &&
|
277
|
|
- ((pkt->partner.state & LACP_AGGREGATION) ==
|
278
|
|
- (lacp.pkt.actor.state & LACP_AGGREGATION)))
|
279
|
|
- {
|
280
|
|
- lacp.pkt.partner.state |= LACP_SYNCHRONIZATION;
|
281
|
|
- }
|
282
|
|
- if (!(pkt->actor.state & LACP_AGGREGATION)) {
|
283
|
|
- lacp.pkt.partner.state |= LACP_SYNCHRONIZATION;
|
284
|
|
- }
|
285
|
|
-
|
286
|
|
- /* ACTIVITY? */
|
287
|
|
-}
|
288
|
|
-
|
289
|
|
-static inline int lacp_timer_expired(unsigned long now, unsigned long when)
|
290
|
|
-{
|
291
|
|
- return when && (now > when);
|
292
|
|
-}
|
293
|
|
-
|
294
|
|
-static inline void lacp_start_periodic_timer(unsigned long now)
|
295
|
|
-{
|
296
|
|
- if ((lacp.pkt.partner.state & LACP_ACTIVITY) ||
|
297
|
|
- (lacp.pkt.actor.state & LACP_ACTIVITY)) {
|
298
|
|
- lacp.periodic_timer = now +
|
299
|
|
- (((lacp.pkt.partner.state & LACP_TIMEOUT)?
|
300
|
|
- FAST_PERIODIC_TIME : SLOW_PERIODIC_TIME));
|
301
|
|
- }
|
302
|
|
-}
|
303
|
|
-
|
304
|
|
-static inline void lacp_start_current_while_timer(unsigned long now)
|
305
|
|
-{
|
306
|
|
- lacp.current_while_timer = now +
|
307
|
|
- ((lacp.pkt.actor.state & LACP_TIMEOUT) ?
|
308
|
|
- SHORT_TIMEOUT_TIME : LONG_TIMEOUT_TIME);
|
309
|
|
-
|
310
|
|
- lacp.pkt.actor.state &= ~LACP_EXPIRED;
|
311
|
|
-}
|
312
|
|
-
|
313
|
|
-static void send_lacp_reports(unsigned long now, int ntt)
|
314
|
|
-{
|
315
|
|
- if (memcmp(nic.node_addr, lacp.pkt.actor.system, ETH_ALEN) != 0) {
|
316
|
|
- lacp_init_state(nic.node_addr);
|
317
|
|
- }
|
318
|
|
- /* If the remote information has expired I need to take action */
|
319
|
|
- if (lacp_timer_expired(now, lacp.current_while_timer)) {
|
320
|
|
- if (!(lacp.pkt.actor.state & LACP_EXPIRED)) {
|
321
|
|
- lacp.pkt.partner.state &= ~LACP_SYNCHRONIZATION;
|
322
|
|
- lacp.pkt.partner.state |= LACP_TIMEOUT;
|
323
|
|
- lacp.pkt.actor.state |= LACP_EXPIRED;
|
324
|
|
- lacp.current_while_timer = now + SHORT_TIMEOUT_TIME;
|
325
|
|
- ntt = 1;
|
326
|
|
- }
|
327
|
|
- else {
|
328
|
|
- lacp_init_state(nic.node_addr);
|
329
|
|
- }
|
330
|
|
- }
|
331
|
|
- /* If the periodic timer has expired I need to transmit */
|
332
|
|
- if (lacp_timer_expired(now, lacp.periodic_timer)) {
|
333
|
|
- ntt = 1;
|
334
|
|
- /* Reset by lacp_start_periodic_timer */
|
335
|
|
- }
|
336
|
|
- if (ntt) {
|
337
|
|
- eth_transmit(slow_dest, ETH_P_SLOW, sizeof(lacp.pkt), &lacp.pkt);
|
338
|
|
-
|
339
|
|
- /* Restart the periodic timer */
|
340
|
|
- lacp_start_periodic_timer(now);
|
341
|
|
-
|
342
|
|
- print_lacp("Trasmitted", &lacp.pkt, now);
|
343
|
|
- }
|
344
|
|
-}
|
345
|
|
-
|
346
|
|
-static inline void send_eth_slow_reports(unsigned long now)
|
347
|
|
-{
|
348
|
|
- send_lacp_reports(now, 0);
|
349
|
|
-}
|
350
|
|
-
|
351
|
|
-static inline void process_eth_slow(unsigned short ptype, unsigned long now)
|
352
|
|
-{
|
353
|
|
- union slow_union *pkt;
|
354
|
|
- if ((ptype != ETH_P_SLOW) ||
|
355
|
|
- (nic.packetlen < (ETH_HLEN + sizeof(pkt->header)))) {
|
356
|
|
- return;
|
357
|
|
- }
|
358
|
|
- pkt = (union slow_union *)&nic.packet[ETH_HLEN];
|
359
|
|
- if ((pkt->header.subtype == SLOW_SUBTYPE_LACP) &&
|
360
|
|
- (nic.packetlen >= ETH_HLEN + sizeof(pkt->lacp))) {
|
361
|
|
- int ntt;
|
362
|
|
- if (memcmp(nic.node_addr, lacp.pkt.actor.system, ETH_ALEN) != 0) {
|
363
|
|
- lacp_init_state(nic.node_addr);
|
364
|
|
- }
|
365
|
|
- /* As long as nic.packet is 2 byte aligned all is good */
|
366
|
|
- print_lacp("Received", &pkt->lacp, now);
|
367
|
|
- /* I don't actually implement the MUX or SELECT
|
368
|
|
- * machines.
|
369
|
|
- *
|
370
|
|
- * What logically happens when the client and I
|
371
|
|
- * disagree about an aggregator is the current
|
372
|
|
- * aggregtator is unselected. The MUX machine places
|
373
|
|
- * me in DETACHED. The SELECT machine runs and
|
374
|
|
- * reslects the same aggregator. If I go through
|
375
|
|
- * these steps fast enough an outside observer can not
|
376
|
|
- * notice this.
|
377
|
|
- *
|
378
|
|
- * Since the process will not generate any noticeable
|
379
|
|
- * effect it does not need an implmenetation. This
|
380
|
|
- * keeps the code simple and the code and binary
|
381
|
|
- * size down.
|
382
|
|
- */
|
383
|
|
- /* lacp_update_selected(&pkt->lacp); */
|
384
|
|
- ntt = lacp_update_ntt(&pkt->lacp);
|
385
|
|
- lacp_record_pdu(&pkt->lacp);
|
386
|
|
- lacp_start_current_while_timer(now);
|
387
|
|
- send_lacp_reports(now, ntt);
|
388
|
|
- }
|
389
|
|
- /* If we receive a marker information packet return it */
|
390
|
|
- else if ((pkt->header.subtype == SLOW_SUBTYPE_MARKER) &&
|
391
|
|
- (nic.packetlen >= ETH_HLEN + sizeof(pkt->marker)) &&
|
392
|
|
- (pkt->marker.tlv_type == MARKER_TLV_INFO) &&
|
393
|
|
- (pkt->marker.marker_length == 0x16))
|
394
|
|
- {
|
395
|
|
- pkt->marker.tlv_type = MARKER_TLV_RESPONSE;
|
396
|
|
- eth_transmit(slow_dest, ETH_P_SLOW,
|
397
|
|
- sizeof(pkt->marker), &pkt->marker);
|
398
|
|
- }
|
399
|
|
-
|
400
|
|
- }
|
401
|
|
-#else
|
402
|
|
-
|
403
|
|
-#define send_eth_slow_reports(now) do {} while(0)
|
404
|
|
-#define process_eth_slow(ptype, now) do {} while(0)
|
405
|
|
-
|
406
|
|
-#endif
|