Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

proto_eth_slow.c 12KB

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