00001
00002 #ifdef PROTO_LACP
00003 #if 0
00004 #include "nic.h"
00005 #include "timer.h"
00006 #endif
00007
00008 #define LACP_DEBUG 0
00009
00010
00011
00012 #define SLOW_DST_MAC "\x01\x80\xc2\x00\x00\x02"
00013 static const char slow_dest[] = SLOW_DST_MAC;
00014
00015
00016 #define SLOW_SUBTYPE_LACP 1
00017 #define SLOW_SUBTYPE_MARKER 2
00018
00019 struct slow_header {
00020 uint8_t subtype;
00021 };
00022
00023 struct lacp_info {
00024 uint16_t system_priority;
00025 uint8_t system[ETH_ALEN];
00026 uint16_t key;
00027 uint16_t port_priority;
00028 uint16_t port;
00029 uint8_t state;
00030 uint8_t reserved[3];
00031 } PACKED;
00032
00033 #define LACP_CMP_LEN (2 + 6 + 2 + 2 + 2)
00034 #define LACP_CP_LEN (2 + 6 + 2 + 2 + 2 + 1)
00035
00036
00037 struct slow_lacp {
00038 uint8_t subtype;
00039 uint8_t version_number;
00040 uint8_t tlv_type_actor_info;
00041 #define LACP_TLV_TERMINATOR 0
00042 #define LACP_TLV_ACTOR 1
00043 #define LACP_TLV_PARTNER 2
00044 #define LACP_TLV_COLLECTOR 3
00045 uint8_t actor_information_length;
00046 struct lacp_info actor;
00047 uint8_t tlv_type_partner_info;
00048 uint8_t partner_information_length;
00049 struct lacp_info partner;
00050 uint8_t tlv_type_collector_info;
00051 uint8_t collector_information_length;
00052 uint16_t collector_max_delay;
00053 uint8_t reserved_12[12];
00054 uint8_t tlv_type_terminator;
00055 uint8_t terminator_length;
00056 uint8_t reserved_50[50];
00057 } PACKED;
00058
00059
00060 struct slow_marker {
00061 uint8_t subtype;
00062 uint8_t version_number;
00063 uint8_t tlv_type;
00064 #define MARKER_TLV_TERMINATOR 0
00065 #define MARKER_TLV_INFO 1
00066 #define MARKER_TLV_RESPONSE 2
00067 uint8_t marker_length;
00068 uint16_t requester_port;
00069 uint8_t requester_system[ETH_ALEN];
00070 uint32_t requester_transaction_id;
00071 uint16_t pad;
00072 uint8_t tlv_type_terminator;
00073 uint8_t terminator_length;
00074 uint8_t reserved_90[90];
00075 } PACKED;
00076
00077 union slow_union {
00078 struct slow_header header;
00079 struct slow_lacp lacp;
00080 struct slow_marker marker;
00081 };
00082
00083 #define FAST_PERIODIC_TIME (1*TICKS_PER_SEC)
00084 #define SLOW_PERIODIC_TIME (30*TICKS_PER_SEC)
00085 #define SHORT_TIMEOUT_TIME (3*FAST_PERIODIC_TIME)
00086 #define LONG_TIMEOUT_TIME (3*SLOW_PERIODIC_TIME)
00087 #define CHURN_DETECTION_TIME (60*TICKS_PER_SEC)
00088 #define AGGREGATE_WAIT_TIME (2*TICKS_PER_SEC)
00089
00090 #define LACP_ACTIVITY (1 << 0)
00091 #define LACP_TIMEOUT (1 << 1)
00092 #define LACP_AGGREGATION (1 << 2)
00093 #define LACP_SYNCHRONIZATION (1 << 3)
00094 #define LACP_COLLECTING (1 << 4)
00095 #define LACP_DISTRIBUTING (1 << 5)
00096 #define LACP_DEFAULTED (1 << 6)
00097 #define LACP_EXPIRED (1 << 7)
00098
00099 #define UNSELECTED 0
00100 #define STANDBY 1
00101 #define SELECTED 2
00102
00103
00104 struct lacp_state {
00105 struct slow_lacp pkt;
00106 unsigned long current_while_timer;
00107 unsigned long periodic_timer;
00108 };
00109
00110 static struct lacp_state lacp;
00111
00112
00113 #if LACP_DEBUG > 0
00114 static void print_lacp_state(uint8_t state)
00115 {
00116 printf("%hhx", state);
00117 if (state & LACP_ACTIVITY) {
00118 printf(" Activity");
00119 }
00120 if (state & LACP_TIMEOUT) {
00121 printf(" Timeout");
00122 }
00123 if (state & LACP_AGGREGATION) {
00124 printf(" Aggregation");
00125 }
00126 if (state & LACP_SYNCHRONIZATION) {
00127 printf(" Syncronization");
00128 }
00129 if (state & LACP_COLLECTING) {
00130 printf(" Collecting");
00131 }
00132 if (state & LACP_DISTRIBUTING) {
00133 printf(" Distributing");
00134 }
00135 if (state & LACP_DEFAULTED) {
00136 printf(" Defaulted");
00137 }
00138 if (state & LACP_EXPIRED) {
00139 printf(" Expired");
00140 }
00141 printf("\n");
00142 }
00143
00144 static inline void print_lacpdu(struct slow_lacp *pkt)
00145 {
00146 printf("subtype version: %hhx %hhx\n",
00147 pkt->subtype, pkt->version_number);
00148 printf("actor_tlv %hhx", pkt->tlv_type_actor_info);
00149 printf(" len: %hhx (\n", pkt->actor_information_length);
00150 printf(" sys_pri: %hx", ntohs(pkt->actor.system_priority));
00151 printf(" mac: %!", pkt->actor.system);
00152 printf(" key: %hx", ntohs(pkt->actor.key));
00153 printf(" port_pri: %hx", ntohs(pkt->actor.port_priority));
00154 printf(" port: %hx\n", ntohs(pkt->actor.port));
00155 printf(" state: ");
00156 print_lacp_state(pkt->actor.state);
00157 #if LACP_DEBUG > 1
00158 printf(" reserved: %hhx %hhx %hhx\n",
00159 pkt->actor.reserved[0], pkt->actor.reserved[1], pkt->actor.reserved[2]);
00160 #endif
00161 printf(")\n");
00162 printf("partner_tlv: %hhx", pkt->tlv_type_partner_info);
00163 printf(" len: %hhx (\n", pkt->partner_information_length);
00164 printf(" sys_pri: %hx", ntohs(pkt->partner.system_priority));
00165 printf(" mac: %!", pkt->partner.system);
00166 printf(" key: %hx", ntohs(pkt->partner.key));
00167 printf(" port_pri: %hx", ntohs(pkt->partner.port_priority));
00168 printf(" port: %hx\n", ntohs(pkt->partner.port));
00169 printf(" state: ");
00170 print_lacp_state(pkt->partner.state);
00171 #if LACP_DEBUG > 1
00172 printf(" reserved: %hhx %hhx %hhx\n",
00173 pkt->partner.reserved[0], pkt->partner.reserved[1], pkt->partner.reserved[2]);
00174 #endif
00175 printf(")\n");
00176 printf("collector_tlv: %hhx ", pkt->tlv_type_collector_info);
00177 printf(" len: %hhx (", pkt->collector_information_length);
00178 printf(" max_delay: %hx", ntohs(pkt->collector_max_delay));
00179 #if LACP_DEBUG > 1
00180 printf("reserved_12: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n",
00181 pkt->reserved_12[0], pkt->reserved_12[1], pkt->reserved_12[2],
00182 pkt->reserved_12[3], pkt->reserved_12[4], pkt->reserved_12[5],
00183 pkt->reserved_12[6], pkt->reserved_12[7], pkt->reserved_12[8],
00184 pkt->reserved_12[9], pkt->reserved_12[10], pkt->reserved_12[11]);
00185 #endif
00186 printf(" )\n");
00187 printf("terminator_tlv: %hhx", pkt->tlv_type_terminator);
00188 printf(" len: %hhx ()\n", pkt->terminator_length);
00189 }
00190
00191 static inline unsigned long lacp_timer_val(unsigned long now, unsigned long when)
00192 {
00193 return when?(when - now)/TICKS_PER_SEC : 0;
00194 }
00195 static void print_lacp(const char *which, struct slow_lacp *pkt, unsigned long now)
00196 {
00197 printf("%s\n", which);
00198 print_lacpdu(pkt);
00199 printf("timers: c %ds p %ds\n",
00200 lacp_timer_val(now, lacp.current_while_timer),
00201 lacp_timer_val(now, lacp.periodic_timer)
00202 );
00203 printf("\n");
00204 }
00205 #else
00206 #define print_lacp(which, pkt, now) do {} while(0)
00207 #endif
00208
00209 static void lacp_init_state(const uint8_t *mac)
00210 {
00211 memset(&lacp, 0, sizeof(lacp));
00212
00213
00214 lacp.pkt.subtype = 1;
00215 lacp.pkt.version_number = 1;
00216
00217
00218
00219 lacp.pkt.tlv_type_actor_info = LACP_TLV_ACTOR;
00220 lacp.pkt.actor_information_length = 0x14;
00221 lacp.pkt.actor.system_priority = htons(1);
00222 memcpy(lacp.pkt.actor.system, mac, ETH_ALEN);
00223 lacp.pkt.actor.key = htons(1);
00224 lacp.pkt.actor.port = htons(1);
00225 lacp.pkt.actor.port_priority = htons(1);
00226 lacp.pkt.actor.state =
00227 LACP_SYNCHRONIZATION |
00228 LACP_COLLECTING |
00229 LACP_DISTRIBUTING |
00230 LACP_DEFAULTED;
00231
00232
00233 lacp.pkt.tlv_type_partner_info = LACP_TLV_PARTNER;
00234 lacp.pkt.partner_information_length = 0x14;
00235 lacp.pkt.partner.system_priority = htons(1);
00236
00237 lacp.pkt.partner.key = htons(1);
00238 lacp.pkt.partner.port = htons(1);
00239 lacp.pkt.partner.port_priority = htons(1);
00240 lacp.pkt.partner.state =
00241 LACP_ACTIVITY |
00242 LACP_SYNCHRONIZATION |
00243 LACP_COLLECTING |
00244 LACP_DISTRIBUTING |
00245 LACP_DEFAULTED;
00246
00247 lacp.pkt.tlv_type_collector_info = LACP_TLV_COLLECTOR;
00248 lacp.pkt.collector_information_length = 0x10;
00249 lacp.pkt.collector_max_delay = htons(0x8000);
00250
00251 lacp.pkt.tlv_type_terminator = LACP_TLV_TERMINATOR;
00252 lacp.pkt.terminator_length = 0;
00253 }
00254
00255 #define LACP_NTT_MASK (LACP_ACTIVITY | LACP_TIMEOUT | \
00256 LACP_SYNCHRONIZATION | LACP_AGGREGATION)
00257
00258 static inline int lacp_update_ntt(struct slow_lacp *pkt)
00259 {
00260 int ntt = 0;
00261 if ((memcmp(&pkt->partner, &lacp.pkt.actor, LACP_CMP_LEN) != 0) ||
00262 ((pkt->partner.state & LACP_NTT_MASK) !=
00263 (lacp.pkt.actor.state & LACP_NTT_MASK)))
00264 {
00265 ntt = 1;
00266 }
00267 return ntt;
00268 }
00269
00270 static inline void lacp_record_pdu(struct slow_lacp *pkt)
00271 {
00272 memcpy(&lacp.pkt.partner, &pkt->actor, LACP_CP_LEN);
00273
00274 lacp.pkt.actor.state &= ~LACP_DEFAULTED;
00275 lacp.pkt.partner.state &= ~LACP_SYNCHRONIZATION;
00276 if ((memcmp(&pkt->partner, &lacp.pkt.actor, LACP_CMP_LEN) == 0) &&
00277 ((pkt->partner.state & LACP_AGGREGATION) ==
00278 (lacp.pkt.actor.state & LACP_AGGREGATION)))
00279 {
00280 lacp.pkt.partner.state |= LACP_SYNCHRONIZATION;
00281 }
00282 if (!(pkt->actor.state & LACP_AGGREGATION)) {
00283 lacp.pkt.partner.state |= LACP_SYNCHRONIZATION;
00284 }
00285
00286
00287 }
00288
00289 static inline int lacp_timer_expired(unsigned long now, unsigned long when)
00290 {
00291 return when && (now > when);
00292 }
00293
00294 static inline void lacp_start_periodic_timer(unsigned long now)
00295 {
00296 if ((lacp.pkt.partner.state & LACP_ACTIVITY) ||
00297 (lacp.pkt.actor.state & LACP_ACTIVITY)) {
00298 lacp.periodic_timer = now +
00299 (((lacp.pkt.partner.state & LACP_TIMEOUT)?
00300 FAST_PERIODIC_TIME : SLOW_PERIODIC_TIME));
00301 }
00302 }
00303
00304 static inline void lacp_start_current_while_timer(unsigned long now)
00305 {
00306 lacp.current_while_timer = now +
00307 ((lacp.pkt.actor.state & LACP_TIMEOUT) ?
00308 SHORT_TIMEOUT_TIME : LONG_TIMEOUT_TIME);
00309
00310 lacp.pkt.actor.state &= ~LACP_EXPIRED;
00311 }
00312
00313 static void send_lacp_reports(unsigned long now, int ntt)
00314 {
00315 if (memcmp(nic.node_addr, lacp.pkt.actor.system, ETH_ALEN) != 0) {
00316 lacp_init_state(nic.node_addr);
00317 }
00318
00319 if (lacp_timer_expired(now, lacp.current_while_timer)) {
00320 if (!(lacp.pkt.actor.state & LACP_EXPIRED)) {
00321 lacp.pkt.partner.state &= ~LACP_SYNCHRONIZATION;
00322 lacp.pkt.partner.state |= LACP_TIMEOUT;
00323 lacp.pkt.actor.state |= LACP_EXPIRED;
00324 lacp.current_while_timer = now + SHORT_TIMEOUT_TIME;
00325 ntt = 1;
00326 }
00327 else {
00328 lacp_init_state(nic.node_addr);
00329 }
00330 }
00331
00332 if (lacp_timer_expired(now, lacp.periodic_timer)) {
00333 ntt = 1;
00334
00335 }
00336 if (ntt) {
00337 eth_transmit(slow_dest, ETH_P_SLOW, sizeof(lacp.pkt), &lacp.pkt);
00338
00339
00340 lacp_start_periodic_timer(now);
00341
00342 print_lacp("Trasmitted", &lacp.pkt, now);
00343 }
00344 }
00345
00346 static inline void send_eth_slow_reports(unsigned long now)
00347 {
00348 send_lacp_reports(now, 0);
00349 }
00350
00351 static inline void process_eth_slow(unsigned short ptype, unsigned long now)
00352 {
00353 union slow_union *pkt;
00354 if ((ptype != ETH_P_SLOW) ||
00355 (nic.packetlen < (ETH_HLEN + sizeof(pkt->header)))) {
00356 return;
00357 }
00358 pkt = (union slow_union *)&nic.packet[ETH_HLEN];
00359 if ((pkt->header.subtype == SLOW_SUBTYPE_LACP) &&
00360 (nic.packetlen >= ETH_HLEN + sizeof(pkt->lacp))) {
00361 int ntt;
00362 if (memcmp(nic.node_addr, lacp.pkt.actor.system, ETH_ALEN) != 0) {
00363 lacp_init_state(nic.node_addr);
00364 }
00365
00366 print_lacp("Received", &pkt->lacp, now);
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 ntt = lacp_update_ntt(&pkt->lacp);
00385 lacp_record_pdu(&pkt->lacp);
00386 lacp_start_current_while_timer(now);
00387 send_lacp_reports(now, ntt);
00388 }
00389
00390 else if ((pkt->header.subtype == SLOW_SUBTYPE_MARKER) &&
00391 (nic.packetlen >= ETH_HLEN + sizeof(pkt->marker)) &&
00392 (pkt->marker.tlv_type == MARKER_TLV_INFO) &&
00393 (pkt->marker.marker_length == 0x16))
00394 {
00395 pkt->marker.tlv_type = MARKER_TLV_RESPONSE;
00396 eth_transmit(slow_dest, ETH_P_SLOW,
00397 sizeof(pkt->marker), &pkt->marker);
00398 }
00399
00400 }
00401 #else
00402
00403 #define send_eth_slow_reports(now) do {} while(0)
00404 #define process_eth_slow(ptype, now) do {} while(0)
00405
00406 #endif