NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
Ethernet_Mac.c
1/************************************************************************************
2* Copyright (C) 2023 *
3* TETCOS, Bangalore. India *
4* *
5* Tetcos owns the intellectual property rights in the Product and its content. *
6* The copying, redistribution, reselling or publication of any or all of the *
7* Product or its content without express prior written consent of Tetcos is *
8* prohibited. Ownership and / or any other right relating to the software and all *
9* intellectual property rights therein shall remain at all times with Tetcos. *
10* *
11* This source code is licensed per the NetSim license agreement. *
12* *
13* No portion of this source code may be used as the basis for a derivative work, *
14* or used, for any purpose other than its intended use per the NetSim license *
15* agreement. *
16* *
17* This source code and the algorithms contained within it are confidential trade *
18* secrets of TETCOS and may not be used as the basis for any other software, *
19* hardware, product or service. *
20* *
21* Author: Shashi Kant Suman *
22* *
23* ----------------------------------------------------------------------------------*/
24#include "main.h"
25#include "Ethernet.h"
26#include "Ethernet_enum.h"
27#include "../Firewall/Firewall.h"
28
29#define ETHERNET_FRAME_HEADER_LEN 26 //Bytes
30
31NETSIM_ID find_forward_interface(ptrETH_LAN lan, NetSim_PACKET* packet)
32{
33#pragma warning(disable:4189) // For debug
34 PNETSIM_MACADDRESS src = packet->pstruMacData->szSourceMac;
35#pragma warning(default:4189)
36 PNETSIM_MACADDRESS dest = packet->pstruMacData->szDestMac;
37 ptrSWITCHTABLE table = SWITCHTABLE_FIND(lan, dest);
38 return table ? table->outPort : 0;
39}
40
41void send_to_phy(NETSIM_ID d, NETSIM_ID in, NetSim_PACKET* packet, double time)
42{
43 NetSim_EVENTDETAILS pevent;
44 memset(&pevent, 0, sizeof pevent);
45 pevent.dEventTime = time;
46 pevent.dPacketSize = packet->pstruMacData->dPacketSize;
47 if (packet->pstruAppData)
48 {
49 pevent.nApplicationId = packet->pstruAppData->nApplicationId;
50 pevent.nSegmentId = packet->pstruAppData->nSegmentId;
51 }
52 pevent.nDeviceId = d;
53 pevent.nDeviceType = DEVICE_TYPE(d);
54 pevent.nEventType = PHYSICAL_OUT_EVENT;
55 pevent.nInterfaceId = in;
56 pevent.nPacketId = packet->nPacketId;
57 pevent.nProtocolId = MAC_PROTOCOL_IEEE802_3;
58 pevent.pPacket = packet;
59 fnpAddEvent(&pevent);
60}
61
62static void add_mac_header(NetSim_PACKET* packet, double time)
63{
64 packet->pstruMacData->dPayload = packet->pstruNetworkData->dPacketSize;
65 packet->pstruMacData->dOverhead = ETHERNET_FRAME_HEADER_LEN;
66 packet->pstruMacData->dPacketSize = packet->pstruMacData->dPayload +
67 packet->pstruMacData->dOverhead;
68
69 packet->pstruMacData->dArrivalTime = time;
70 packet->pstruMacData->dEndTime = time;
71 packet->pstruMacData->dStartTime = time;
72
73 packet->pstruMacData->nMACProtocol = MAC_PROTOCOL_IEEE802_3;
74}
75
76static int packet_arrive_from_network_layer()
77{
78 NETSIM_ID d = pstruEventDetails->nDeviceId;
79 NETSIM_ID in = pstruEventDetails->nInterfaceId;
80 double time = pstruEventDetails->dEventTime;
81
82 NetSim_PACKET* packet = fn_NetSim_Packet_GetPacketFromBuffer(DEVICE_ACCESSBUFFER(d, in), 1);
83 while (packet)
84 {
85 UINT16 vlanId = eth_get_incoming_vlanid(packet, d);
86 NETSIM_ID incoming = eth_get_incoming_port(packet, d);
87 clear_eth_incoming(packet);
88
89 if (vlanId)
90 {
91 vlan_macout_forward_packet(d, in, vlanId, incoming, packet, time);
92 //Take the next packet
93 packet = fn_NetSim_Packet_GetPacketFromBuffer(DEVICE_ACCESSBUFFER(d, in), 1);
94 continue;
95 }
96
97 NETSIM_ID out = 0;
98 ptrETH_LAN lan = GET_ETH_LAN(d, in, 0);
99 if (lan->interfaceCount > 1)
100 {
101 out = find_forward_interface(lan, packet);
102 }
103 else { out = in; }
104
105 add_mac_header(packet, time);
106 if (out)
107 {
108 if (fn_NetSim_MAC_Firewall(d, out, packet, ACLTYPE_OUTBOUND) == ACLACTION_PERMIT)
109 {
110 clear_eth_incoming(packet);
111 send_to_phy(d, out, packet, time);
112 }
113 else
114 fn_NetSim_Packet_FreePacket(packet);
115 }
116 else
117 {
118 UINT j;
119 for (j = 0; j < lan->interfaceCount; j++)
120 {
121 if (lan->ethIfVar[j]->portState == PORTSTATE_BLOCKING)
122 continue;
123
124 NetSim_PACKET* p = fn_NetSim_Packet_CopyPacket(packet);
125 if (fn_NetSim_MAC_Firewall(d, lan->ethIfVar[j]->interfaceId, p, ACLTYPE_OUTBOUND) == ACLACTION_PERMIT &&
126 (lan->ethIfVar[j]->interfaceId != incoming || lan->switchingTechnique == SWITCHINGTECHNIQUE_NULL))
127 {
128 clear_eth_incoming(p);
129 send_to_phy(d, lan->ethIfVar[j]->interfaceId, p, time);
130 }
131 else
132 fn_NetSim_Packet_FreePacket(p);
133 }
134
135 vlan_forward_to_all_trunk(d, packet, lan, time);
136 fn_NetSim_Packet_FreePacket(packet);
137 }
138
139 //Take the next packet
140 packet = fn_NetSim_Packet_GetPacketFromBuffer(DEVICE_ACCESSBUFFER(d, in), 1);
141 }
142 return 0;
143}
144
145int fn_NetSim_Ethernet_HandleMacOut()
146{
147 switch (pstruEventDetails->nSubEventType)
148 {
149 case 0:
150 return packet_arrive_from_network_layer();
151 break;
152 case SEND_CONFIG_BPDU:
153 return multicast_config_bpdu();
154 default:
155 fnNetSimError("Unknown subevent %d for Ethernet in %s",
156 pstruEventDetails->nSubEventType,
157 __FUNCTION__);
158 return -1;
159 }
160}
161
162static bool validate_mac_frame(ptrETH_LAN lan, PNETSIM_MACADDRESS mac)
163{
164 if (lan->ispromiscuousMode)
165 return true;
166
167 if (isBroadcastMAC(mac))
168 return true;
169
170 if (isMulticastMAC(mac))
171 return true;
172
173 if (lan->switchingTechnique)
174 return true;
175
176 UINT i;
177 for (i = 0; i < lan->interfaceCount; i++)
178 {
179 ptrETH_IF inter = lan->ethIfVar[i];
180 PNETSIM_MACADDRESS m = inter->macAddress;
181 if (!MAC_COMPARE(m, mac))
182 return true;
183 }
184 return false;
185}
186
187void check_move_frame_up(NETSIM_ID d,
188 NETSIM_ID in,
189 ptrETH_LAN lan,
190 NetSim_PACKET* packet,
191 double time)
192{
193 PNETSIM_MACADDRESS dest = packet->pstruMacData->szDestMac;
194 bool isforme = validate_mac_frame(lan, dest);
195 if (isforme)
196 {
197 free_eth_hdr(packet);
198 NetSim_EVENTDETAILS pevent;
199 memset(&pevent, 0, sizeof pevent);
200 pevent.dEventTime = time;
201 pevent.dPacketSize = packet->pstruNetworkData->dPacketSize;
202 if (packet->pstruAppData)
203 {
204 pevent.nApplicationId = packet->pstruAppData->nApplicationId;
205 pevent.nSegmentId = packet->pstruAppData->nSegmentId;
206 }
207 pevent.nDeviceId = d;
208 pevent.nDeviceType = DEVICE_TYPE(d);
209 pevent.nEventType = NETWORK_IN_EVENT;
210 pevent.nInterfaceId = in;
211 pevent.nPacketId = packet->nPacketId;
212 pevent.nProtocolId = NW_PROTOCOL_IPV4;
213 pevent.pPacket = packet;
214 fnpAddEvent(&pevent);
215 }
216 else
217 {
218 fn_NetSim_Packet_FreePacket(packet);
219 pstruEventDetails->pPacket = NULL;
220 }
221}
222
223static void forward_packet_to_other_protocol(NETSIM_ID d,
224 NETSIM_ID in,
225 NetSim_PACKET* packet,
226 double time)
227{
228 NetSim_BUFFER* buffer = DEVICE_ACCESSBUFFER(d, in);
229 NetSim_PACKET* p = fn_NetSim_Packet_CopyPacket(packet);
230
231 if (!fn_NetSim_GetBufferStatus(buffer))
232 {
233 NetSim_EVENTDETAILS pevent;
234 memset(&pevent, 0, sizeof pevent);
235 pevent.dEventTime = time;
236 pevent.dPacketSize = p->pstruNetworkData->dPacketSize;
237 if (p->pstruAppData)
238 {
239 pevent.nApplicationId = p->pstruAppData->nApplicationId;
240 pevent.nSegmentId = p->pstruAppData->nSegmentId;
241 }
242 pevent.nDeviceId = d;
243 pevent.nDeviceType = DEVICE_TYPE(d);
244 pevent.nEventType = MAC_OUT_EVENT;
245 pevent.nInterfaceId = in;
246 pevent.nPacketId = p->nPacketId;
247 pevent.nProtocolId = DEVICE_MACLAYER(d, in)->nMacProtocolId;
248 fnpAddEvent(&pevent);
249 }
250 fn_NetSim_Packet_AddPacketToList(buffer, p, 0);
251}
252
253void forward_frame(NETSIM_ID d,
254 NETSIM_ID in,
255 ptrETH_LAN lan,
256 NetSim_PACKET* packet,
257 double time)
258{
259
260 NETSIM_ID f = find_forward_interface(lan, packet);
261
262 if (f)
263 {
264 if (fn_NetSim_MAC_Firewall(d, f, packet, ACLTYPE_OUTBOUND) == ACLACTION_PERMIT)
265 {
266 clear_eth_incoming(packet);
267 send_to_phy(d, f, packet, time);
268 }
269 else
270 fn_NetSim_Packet_FreePacket(packet);
271 }
272 else
273 {
274 if (DEVICE_TYPE(d) == SWITCH)
275 {
276 UINT j;
277 for (j = 0; j < lan->interfaceCount; j++)
278 {
279 if (lan->ethIfVar[j]->interfaceId == in)
280 continue;
281
282 if (lan->ethIfVar[j]->portState == PORTSTATE_BLOCKING)
283 continue;
284
285 NetSim_PACKET* p = fn_NetSim_Packet_CopyPacket(packet);
286 if (fn_NetSim_MAC_Firewall(d, lan->ethIfVar[j]->interfaceId, packet, ACLTYPE_OUTBOUND) == ACLACTION_PERMIT)
287 {
288 clear_eth_incoming(p);
289 send_to_phy(d, lan->ethIfVar[j]->interfaceId, p, time);
290 }
291 else
292 fn_NetSim_Packet_FreePacket(p);
293 }
294
295 vlan_forward_to_all_trunk(d, packet, lan, time);
296 }
297 else if(!lan->lanIP)
298 {
299 NETSIM_ID j;
300 //Forward to all other interface other than switch
301 for (j = 0; j < DEVICE(d)->nNumOfInterface; j++)
302 {
303 if (j + 1 == in ||
304 isVirtualInterface(d,j+1))
305 continue;
306
307 forward_packet_to_other_protocol(d, j+1, packet, time);
308 }
309 }
310 fn_NetSim_Packet_FreePacket(packet);
311 }
312}
313
314static bool decide_move_up(ptrETH_LAN lan, PNETSIM_MACADDRESS destMAC, SWITCHING_TECHNIQUE sw)
315{
316 if (isBroadcastMAC(destMAC) &&
317 sw != SWITCHINGTECHNIQUE_NULL) return false;
318
319 if (lan->lanIP)
320 return true;
321 else
322 return false;
323}
324
325static void ethernet_mac_process_frame()
326{
327 NETSIM_ID d = pstruEventDetails->nDeviceId;
328 NETSIM_ID in = pstruEventDetails->nInterfaceId;
329 double time = pstruEventDetails->dEventTime;
330 NetSim_PACKET* packet = pstruEventDetails->pPacket;
331
332 if (fn_NetSim_MAC_Firewall(d, in, packet, ACLTYPE_INBOUND) == ACLACTION_DENY)
333 {
334 fn_NetSim_Packet_FreePacket(packet);
335 return;
336 }
337
338#pragma warning(disable:4189) // For debug
339 PNETSIM_MACADDRESS dest = packet->pstruMacData->szDestMac;
340#pragma warning(default:4189)
341
342 PNETSIM_MACADDRESS src = packet->pstruMacData->szSourceMac;
343
344 ptrETH_LAN lan = GET_ETH_LAN(d, in, 0);
345 if (lan->switchingTechnique)
346 SWITCHTABLE_NEW(lan, src, in);
347
348 bool isTag = isVLANTagPresent(packet);
349 store_eth_param_macin(packet, d, in, lan);
350
351 bool isMoveup = decide_move_up(lan, dest, lan->switchingTechnique);
352 if (isMoveup)
353 {
354 check_move_frame_up(d, in, lan, packet, time);
355 }
356 else
357 {
358 if (isTag)
359 vlan_macin_forward_packet();
360 else
361 forward_frame(d, in, lan, packet, time);
362 }
363}
364
365int fn_NetSim_Ethernet_HandleMacIn()
366{
367 NetSim_PACKET* packet = pstruEventDetails->pPacket;
368 if (packet->nControlDataType == ETH_CONFIGBPDU)
369 process_configbpdu();
370 else
371 ethernet_mac_process_frame();
372 return 0;
373}