17#include "Ethernet_enum.h"
19static void send_config_bpdu(NETSIM_ID d, UINT lanId,
double time);
21static char* eth_get_lowest_mac(ptrETH_LAN lan)
24 PNETSIM_MACADDRESS ret = NULL;
25 for (i = 0; i < lan->interfaceCount; i++)
27 ptrETH_IF in = lan->ethIfVar[i];
30 else if (in->macAddress->nmacaddress < ret->nmacaddress)
33 return ret->szmacaddress;
36static void configure_switch_id(ptrETH_LAN lan)
39 strcpy(
id, eth_get_lowest_mac(lan));
40 lan->spt->switchId = calloc(20,
sizeof(
char));
41 sprintf(lan->spt->switchId,
"%d%s", lan->spt->priority,
id);
44static void eth_spt_init_port(NETSIM_ID d, UINT lanId)
46 ptrETH_VAR eth = GET_ETH_VAR(d);
47 ptrETH_LAN lan = eth->lanVar[lanId];
50 for (i = 0; i < lan->interfaceCount; i++)
53 NETSIM_ID ifi = lan->interfaceId[i];
54 NETSIM_ID l = fn_NetSim_Stack_GetConnectedDevice(d, ifi, &c, &ci);
56 lan->ethIfVar[i]->portState = PORTSTATE_BLOCKING;
58 ptrETH_VAR e = GET_ETH_VAR(c);
61 print_ethernet_log(
"Port %d, Setting status as Forwarding", ifi);
62 lan->ethIfVar[i]->portState = PORTSTATE_FORWARDING;
66 ptrETH_LAN la = GET_ETH_LAN(c, ci, 0);
69 print_ethernet_log(
"Port %d, Setting status as Forwarding", ifi);
70 lan->ethIfVar[i]->portState = PORTSTATE_FORWARDING;
74 lan->ethIfVar[i]->portState = PORTSTATE_FORWARDING;
75 lan->ethIfVar[i]->portType = PORTTYPE_DESIGNATED;
81static void start_spt_for_lan(NETSIM_ID d, UINT lanId)
83 ptrETH_VAR eth = GET_ETH_VAR(d);
84 ptrETH_LAN lan = eth->lanVar[lanId];
86 print_ethernet_log(
"Stating SPT for LAN %d", lanId);
87 eth_spt_init_port(d, lanId);
89 if (!lan->spt->switchId)
90 configure_switch_id(lan);
92 print_ethernet_log(
"Starting as root");
93 lan->spt->rootId = _strdup(lan->spt->switchId);
94 print_ethernet_log(
"Root Id = %s", lan->spt->rootId);
96 print_ethernet_log(
"Sending config BPDU");
97 send_config_bpdu(d, lanId, 0);
100static ptrETH_BPDU create_bpdu(ptrETH_LAN lan)
102 ptrETH_BPDU bpdu = calloc(1,
sizeof* bpdu);
103 bpdu->rootId = lan->spt->rootId;
104 bpdu->rootPathCost = lan->spt->stpCost;
105 bpdu->bridgeId = lan->spt->switchId;
109 bpdu->forwardDelay = 15;
111 print_ethernet_log(
"Root Id = %s, Root path cost = %d, Bridge Id = %s",
118static ptrETH_BPDU copy_bpdu(ptrETH_LAN lan, ptrETH_BPDU b)
120 ptrETH_BPDU bpdu = calloc(1,
sizeof* bpdu);
121 bpdu->rootId = b->rootId;
122 bpdu->rootPathCost = lan->spt->stpCost + b->rootPathCost;
123 bpdu->bridgeId = lan->spt->switchId;
127 bpdu->forwardDelay = 15;
129 print_ethernet_log(
"Root Id = %s, Root path cost = %d, Bridge Id = %s",
136static NetSim_PACKET* create_bpdu_packet(NETSIM_ID d, ptrETH_LAN lan,
double time)
138 NetSim_PACKET* packet = fn_NetSim_Packet_CreatePacket(MAC_LAYER);
139 packet->nControlDataType = ETH_CONFIGBPDU;
140 packet->nPacketType = PacketType_Control;
141 packet->nSourceId = d;
142 packet->nTransmitterId = d;
143 packet->pstruMacData->dArrivalTime = time;
144 packet->pstruMacData->dStartTime = time;
145 packet->pstruMacData->dEndTime = time;
146 packet->pstruMacData->dOverhead = ETH_BPDU_LEN;
147 packet->pstruMacData->dPacketSize = ETH_BPDU_LEN;
148 packet->pstruMacData->nMACProtocol = MAC_PROTOCOL_IEEE802_3;
150 set_eth_hdr(packet, ETH_HDR_CBPDU, create_bpdu(lan), NULL, NULL);
151 packet->pstruMacData->szDestMac = multicastSPTMAC;
152 strcpy(packet->szPacketType,
"CONFIG_BPDU");
156static NetSim_PACKET* copy_bpdu_packet(NETSIM_ID d, ptrETH_LAN lan,
double time, ptrETH_BPDU bpdu)
158 NetSim_PACKET* packet = fn_NetSim_Packet_CreatePacket(MAC_LAYER);
159 packet->nControlDataType = ETH_CONFIGBPDU;
160 packet->nPacketType = PacketType_Control;
161 packet->nSourceId = d;
162 packet->nTransmitterId = d;
163 packet->pstruMacData->dArrivalTime = time;
164 packet->pstruMacData->dStartTime = time;
165 packet->pstruMacData->dEndTime = time;
166 packet->pstruMacData->dOverhead = ETH_BPDU_LEN;
167 packet->pstruMacData->dPacketSize = ETH_BPDU_LEN;
168 packet->pstruMacData->nMACProtocol = MAC_PROTOCOL_IEEE802_3;
170 set_eth_hdr(packet, ETH_HDR_CBPDU, copy_bpdu(lan, bpdu), NULL, NULL);
171 packet->pstruMacData->szDestMac = multicastSPTMAC;
172 strcpy(packet->szPacketType,
"CONFIG_BPDU");
176static void send_config_bpdu(NETSIM_ID d, UINT lanId,
double time)
179 ptrETH_VAR eth = GET_ETH_VAR(d);
180 ptrETH_LAN lan = eth->lanVar[lanId];
182 NetSim_PACKET* packet = create_bpdu_packet(d, lan, time);
185 for (i = 0; i < lan->interfaceCount; i++)
188 NETSIM_ID in = lan->interfaceId[i];
189 NETSIM_ID l = fn_NetSim_Stack_GetConnectedDevice(d, in, &c, &ci);
192 ptrETH_VAR ce = GET_ETH_VAR(c);
195 ptrETH_LAN cl = GET_ETH_LAN(c, ci, 0);
196 if (cl && cl->STPStatus)
198 add_dest_to_packet(packet, c);
207 NetSim_EVENTDETAILS pevent;
208 memset(&pevent, 0,
sizeof pevent);
209 pevent.dEventTime = time;
210 pevent.dPacketSize = packet->pstruMacData->dPacketSize;
211 pevent.nDeviceId = d;
212 pevent.nDeviceType = DEVICE_TYPE(d);
213 pevent.nEventType = MAC_OUT_EVENT;
214 pevent.nProtocolId = MAC_PROTOCOL_IEEE802_3;
215 pevent.pPacket = packet;
216 pevent.nSubEventType = SEND_CONFIG_BPDU;
217 fnpAddEvent(&pevent);
221 fn_NetSim_Packet_FreePacket(packet);
225static void start_spanning_tree_protocol(NETSIM_ID d)
227 ptrETH_VAR eth = GET_ETH_VAR(d);
233 for (i = 0; i < eth->lanCount; i++)
235 if (!eth->lanVar[i]->STPStatus)
237 print_ethernet_log(
"Starting SPT protocol for device %d, LAN %d", d, i + 1);
238 start_spt_for_lan(d, i);
239 print_ethernet_log(
"");
243bool isSingleInterface(NETSIM_ID d, ptrETH_LAN lan)
245 if (lan->interfaceCount == 1)
249 for (i = 0; i< lan->interfaceCount; i++)
251 NETSIM_ID in = lan->interfaceId[i];
253 NETSIM_ID l = fn_NetSim_Stack_GetConnectedDevice(d, in, &c, &ci);
256 ptrETH_VAR eth = GET_ETH_VAR(c);
266void init_spanning_tree_protocol()
269 for (i = 0; i < NETWORK->nDeviceCount; i++)
271 ptrETH_VAR eth = GET_ETH_VAR(i + 1);
275 for (j = 0; j < eth->lanCount; j++)
277 if (!eth->isSPT || (isSingleInterface(i+1, eth->lanVar[j]) &&
278 eth->lanVar[j]->lanIP))
280 eth->lanVar[j]->STPStatus =
false;
281 eth->lanVar[j]->ethIfVar[0]->portState = PORTSTATE_FORWARDING;
282 print_ethernet_log(
"Device %d, Port %d: Setting port state as Forwarding\n",
283 i + 1, eth->lanVar[j]->ethIfVar[0]->interfaceId);
287 eth->lanVar[j]->STPStatus =
true;
291 for (i = 0; i < NETWORK->nDeviceCount; i++)
293 ptrETH_VAR eth = GET_ETH_VAR(i + 1);
297 start_spanning_tree_protocol(i + 1);
301int multicast_config_bpdu()
303 NETSIM_ID d = pstruEventDetails->nDeviceId;
305 NetSim_PACKET* packet = pstruEventDetails->pPacket;
307 NETSIM_ID* dest = get_dest_from_packet(packet, &c);
310 for (i = 0; i < c; i++)
312 NETSIM_ID des = dest[i];
315 p = fn_NetSim_Packet_CopyPacket(packet);
319 NETSIM_ID in = get_interface_id(d, des);
321 NetSim_EVENTDETAILS pevent;
322 memcpy(&pevent, pstruEventDetails,
sizeof pevent);
323 pevent.nEventType = PHYSICAL_OUT_EVENT;
324 pevent.nInterfaceId = in;
325 pevent.nSubEventType = 0;
327 fnpAddEvent(&pevent);
338static COMPARE_BPDU compare_bpdu(ptrETH_BPDU bpdu, ptrETH_SPT spt, NETSIM_ID port)
340 int cid = _stricmp(bpdu->rootId, spt->rootId);
344 if (!_stricmp(spt->rootId, spt->switchId))
350 if (bpdu->rootPathCost == spt->rootPathCost)
352 if (spt->rootPort == port)
357 else if (bpdu->rootPathCost < spt->rootPathCost)
377static void block_port(NETSIM_ID d, ptrETH_LAN lan, NETSIM_ID in)
379 print_ethernet_log(
"Setting switch %d, port %d state as BLOCKED", d, in);
380 ptrETH_IF inter = GET_ETH_IF(lan, in);
381 inter->portState = PORTSTATE_BLOCKING;
382 inter->portType = PORTTYPE_NONDESIGNATED;
385static void forward_port(NETSIM_ID d, ptrETH_LAN lan, NETSIM_ID in)
387 print_ethernet_log(
"Setting switch %d, port %d state as FORWARDING", d, in);
388 ptrETH_IF inter = GET_ETH_IF(lan, in);
389 inter->portState = PORTSTATE_FORWARDING;
392static void update_spt(ptrETH_SPT spt, ptrETH_BPDU bpdu, NETSIM_ID port)
394 print_ethernet_log(
"Updating SPT data");
395 spt->rootId = bpdu->rootId;
396 spt->rootPathCost = bpdu->rootPathCost;
397 spt->rootPort = port;
398 print_ethernet_log(
"Root id = %s, Cost = %d, Root port = %d", spt->rootId, spt->rootPathCost, port);
401static void mark_port(ptrETH_LAN lan, NETSIM_ID port)
404 lan->spt->rootPort = port;
405 for (i = 0; i < lan->interfaceCount; i++)
407 ptrETH_IF inter = lan->ethIfVar[i];
408 if (inter->interfaceId == port)
410 inter->portType = PORTTYPE_ROOT;
414 inter->portType = PORTTYPE_DESIGNATED;
419static void mark_port_as_nondesignated(ptrETH_LAN lan, NETSIM_ID port)
422 for (i = 0; i < lan->interfaceCount; i++)
424 ptrETH_IF inter = lan->ethIfVar[i];
425 if (inter->interfaceId == port)
427 inter->portType = PORTTYPE_NONDESIGNATED;
433static void forward_bpdu(NETSIM_ID d, NETSIM_ID inter,
double time, ptrETH_LAN lan, ptrETH_BPDU configBPDU)
437 print_ethernet_log(
"Forwarding config BPDU");
438 NetSim_PACKET* packet = copy_bpdu_packet(d, lan, time, configBPDU);
441 for (i = 0; i < lan->interfaceCount; i++)
444 NETSIM_ID in = lan->interfaceId[i];
448 NETSIM_ID l = fn_NetSim_Stack_GetConnectedDevice(d, in, &c, &ci);
451 ptrETH_VAR ce = GET_ETH_VAR(c);
454 ptrETH_LAN cl = GET_ETH_LAN(c, ci, 0);
455 if (cl && cl->STPStatus)
457 add_dest_to_packet(packet, c);
466 NetSim_EVENTDETAILS pevent;
467 memset(&pevent, 0,
sizeof pevent);
468 pevent.dEventTime = time;
469 pevent.dPacketSize = packet->pstruMacData->dPacketSize;
470 pevent.nDeviceId = d;
471 pevent.nDeviceType = DEVICE_TYPE(d);
472 pevent.nEventType = MAC_OUT_EVENT;
473 pevent.nProtocolId = MAC_PROTOCOL_IEEE802_3;
474 pevent.pPacket = packet;
475 pevent.nSubEventType = SEND_CONFIG_BPDU;
476 fnpAddEvent(&pevent);
480 fn_NetSim_Packet_FreePacket(packet);
484void process_configbpdu()
486 NETSIM_ID d = pstruEventDetails->nDeviceId;
487 NETSIM_ID in = pstruEventDetails->nInterfaceId;
488 double time = pstruEventDetails->dEventTime;
489 NetSim_PACKET* packet = pstruEventDetails->pPacket;
490 ptrETH_LAN lan = GET_ETH_LAN(d, in, 0);
494 fnNetSimError(
"ConfigBPDU packet is arrived to device %d interface %d. Spanning tree is not enable.",
496 fn_NetSim_Packet_FreePacket(packet);
497 pstruEventDetails->pPacket = NULL;
501 ptrETH_BPDU bpdu = get_eth_hdr_var(packet);
504 fnNetSimError(
"ConfigBPDU hdr is NULL\n");
505 fn_NetSim_Packet_FreePacket(packet);
506 pstruEventDetails->pPacket = NULL;
510 print_ethernet_log(
"Switch %d, Port %d, Time %0.0lf: Config BPDU packet arrives",
513 print_ethernet_log(
"Config BPDU data: Root = %s, Cost = %d, Bridge Id = %d",
517 print_ethernet_log(
"SPT data: Root = %s, cost = %d, Bridge Id = %s, Root port = %d",
519 lan->spt->rootPathCost,
523 COMPARE_BPDU isBlocked = compare_bpdu(bpdu, lan->spt, in);
524 if (isBlocked == BLOCK)
526 block_port(d, lan, in);
528 else if (isBlocked == FORWARD)
531 update_spt(lan->spt, bpdu, in);
532 forward_bpdu(d, in, time, lan, bpdu);
534 fn_NetSim_Packet_FreePacket(packet);
535 pstruEventDetails->pPacket = NULL;
536 print_ethernet_log(
"");
539void print_spanning_tree()
544 sprintf(buf,
"%s%s%s",
548 fp = fopen(buf,
"w");
552 fnSystemError(
"Unable to open SpanningTree.txt file\n");
556 for (i = 0; i < NETWORK->nDeviceCount; i++)
558 ptrETH_VAR eth = GET_ETH_VAR(i + 1);
559 if (!eth || !eth->isSPT)
563 for (j = 0; j < eth->lanCount; j++)
565 ptrETH_LAN lan = eth->lanVar[j];
570 for (k = 0; k < lan->interfaceCount; k++)
572 ptrETH_IF inter = lan->ethIfVar[k];
574 l = fn_NetSim_Stack_GetConnectedDevice(i+1, lan->ethIfVar[k]->interfaceId, &c, &ci);
575 ptrETH_LAN lm = GET_ETH_LAN(c, ci, 0);
579 fprintf(fp,
"%s,%d,%s\n",
581 DEVICE_INTERFACE_CONFIGID(i + 1, inter->interfaceId),
582 inter->portState == PORTSTATE_BLOCKING ?
"BLOCKED" :
"FORWARD");