20ptrIGMP_ROUTER_DB find_or_alloc_multicast_db_router(NETSIM_IPAddress addr,
22 bool* isAlreadyJoined)
24 ptrIGMP_ROUTER_DB r = GET_IGMP_ROUTER(d)->database;
28 if (!IP_COMPARE(r->group, addr))
30 *isAlreadyJoined =
true;
36 *isAlreadyJoined =
false;
37 r = (ptrIGMP_ROUTER_DB)IGMP_ROUTER_DB_ALLOC();
38 r->group = IP_COPY(addr);
39 r->state = RouterState_Querier;
41 IGMP_ROUTER_DB_ADD(d, r);
46static ptrIGMP_ROUTER_DB router_join_multicast_group(NETSIM_ID d, NETSIM_IPAddress group)
48 bool isAlreadyJoined =
false;
49 ptrIGMP_ROUTER router = GET_IGMP_ROUTER(d);
50 ptrIGMP_ROUTER_DB db = find_or_alloc_multicast_db_router(group, d, &isAlreadyJoined);
53 print_igmp_log(
"Calling PIM to join group %s", group->str_ip);
54 pim_join_group(d, group);
59ptrIGMP_ROUTER_DB router_get_multicast_db(NETSIM_ID d,
62 ptrIGMP_ROUTER_DB db = GET_IGMP_ROUTER(d)->database;
65 if (!IP_COMPARE(db->group, ip))
72static void router_delete_multicast_db(NETSIM_ID d,
75 LIST_FREE(&GET_IGMP_ROUTER(d)->database, db);
78static bool isBroadcastInterfacePresent(NETSIM_ID d)
81 for (i = 0; i < DEVICE(d)->nNumOfInterface; i++)
83 if (isBroadcastInterface(d, i + 1))
91static bool isInterfacePresentInDatabase(ptrIGMP_ROUTER_DB db,
95 for (i = 0; i < db->count; i++)
96 if (db->ifids[i] == ifid)
101static bool isOtherInterfacePresentInDatabase(ptrIGMP_ROUTER_DB db,
105 for (i = 0; i < db->count; i++)
106 if (db->ifids[i] != ifid)
111static void router_add_ip_route(ptrIGMP_ROUTER_DB db,
115 if (db->isRouteAlreadyAdded)
119 db->ifids = realloc(db->ifids, db->count *
sizeof* db->ifids);
122 NETSIM_IPAddress* ip = calloc(db->count,
sizeof* ip);
124 for (i = 0; i < db->count; i++)
125 ip[i] = DEVICE_NWADDRESS(d, db->ifids[i]);
127 iptable_change(IP_WRAPPER_GET(d),
129 STR_TO_IP4(
"255.255.255.255"),
141 iptable_add(IP_WRAPPER_GET(d),
143 STR_TO_IP4(
"255.255.255.255"),
147 &DEVICE_NWADDRESS(d, ifid),
151 db->isRouteAlreadyAdded =
true;
152 db->ifids = (NETSIM_ID*)calloc(1,
sizeof* db->ifids);
158void igmp_router_init(NETSIM_ID d)
160 ptrIGMP_VAR var = GET_IGMP_VAR(d);
162 var->StartupQueryInterval = var->QueryInterval / 4;
164 var->StartupQueryCount = var->RobustnessVar;
166 if (isBroadcastInterfacePresent(d))
168 NETSIM_IPAddress g = STR_TO_IP4(
"224.0.0.1");
170 print_igmp_log(
"\nRouter %d, Time 0.0: Joining multicast group %s.",
173 print_igmp_log(
"Sending query msg after %0.0lf.",(
double)IGMP_STARTUP_DELAY);
175 router_join_multicast_group(d, g);
176 send_query_msg(d, g, IGMP_STARTUP_DELAY);
180IP_PROTOCOL_ACTION router_is_ip_present_in_db(NETSIM_ID d, NETSIM_IPAddress ip, NetSim_PACKET* packet)
182 ptrIGMP_ROUTER_DB db = GET_IGMP_ROUTER(d)->database;
185 if (!IP_COMPARE(db->group, ip))
187 if (!isInterfacePresentInDatabase(db, pstruEventDetails->nInterfaceId))
190 if (isOtherInterfacePresentInDatabase(db, pstruEventDetails->nInterfaceId))
191 return ACTION_REROUTE;
200bool router_process_query(NetSim_PACKET* packet, ptrIGMP_MSG msg, NETSIM_ID d)
202 ptrIGMP_ROUTER r = GET_IGMP_ROUTER(d);
204 NETSIM_IPAddress src = packet->pstruNetworkData->szSourceIP;
206 if (isIPForSameDevice(src, d))
209 print_igmp_log(
"\nRouter %d, Time %0.0lf: Query received for group address %s.",
211 pstruEventDetails->dEventTime,
212 msg->GroupAddress->str_ip);
214 NETSIM_IPAddress same = get_ip_from_same_subnet(d, src);
216 if (same->int_ip[0] > src->int_ip[0])
218 print_igmp_log(
"Received from lower ip address %s. Changing state to NonQuerier",
221 ptrIGMP_ROUTER_DB db = router_get_multicast_db(d, msg->GroupAddress);
222 db->state = RouterState_NonQuerier;
223 db->otherQuerierPresentTime = pstruEventDetails->dEventTime;
225 if (!db->isOtherquerierTimerStarted)
227 print_igmp_log(
"Starting Other querier present timer");
228 db->isOtherquerierTimerStarted =
true;
230 EVENT_IGMP_OtherQuerierPresentTimer,
232 pstruEventDetails->dEventTime);
239void igmp_router_processOtherQuerierPresentTime()
241 ptrIGMP_VAR igmp = GET_IGMP_VAR(pstruEventDetails->nDeviceId);
242 ptrIGMP_ROUTER_DB db = router_get_multicast_db(pstruEventDetails->nDeviceId,
243 pstruEventDetails->szOtherDetails);
245 if (pstruEventDetails->dEventTime >=
246 db->otherQuerierPresentTime +
247 igmp->QueryPresentInterval*0.1*SECOND)
250 print_igmp_log(
"\nRouter %d, Time %0.0lf: Other querier present timer expire for group address %s. Starting as querier.",
251 pstruEventDetails->nDeviceId,
252 pstruEventDetails->dEventTime,
255 db->state = RouterState_Querier;
256 send_query_msg(pstruEventDetails->nDeviceId,
258 pstruEventDetails->dEventTime);
263 print_igmp_log(
"\nRouter %d, Time %0.0lf: Query is already received for group address %s. Continuing as Non querier.",
264 pstruEventDetails->nDeviceId,
265 pstruEventDetails->dEventTime,
268 pstruEventDetails->dEventTime = db->otherQuerierPresentTime +
269 igmp->QueryPresentInterval;
270 fnpAddEvent(pstruEventDetails);
274bool router_process_report(NetSim_PACKET* packet,
278 print_igmp_log(
"\nRouter %d, Time %0.0lf: Report received for group address %s.",
280 pstruEventDetails->dEventTime,
281 msg->GroupAddress->str_ip);
283 ptrIGMP_ROUTER_DB r = router_join_multicast_group(d, msg->GroupAddress);
285 r->reportRcvTime = pstruEventDetails->dEventTime;
287 if (!r->isGroupMembershipTimerStarted)
289 print_igmp_log(
"Router %d, Time %0.0lf: Starting group membership timer for group addr %s",
291 pstruEventDetails->dEventTime,
292 msg->GroupAddress->str_ip);
294 EVENT_IGMP_GroupMembershipTimer,
296 pstruEventDetails->dEventTime);
297 r->isGroupMembershipTimerStarted =
true;
298 print_igmp_log(
"Starting query msg");
299 send_query_msg(d, msg->GroupAddress, pstruEventDetails->dEventTime);
301 if(!isInterfacePresentInDatabase(r,pstruEventDetails->nInterfaceId))
302 router_add_ip_route(r, d, pstruEventDetails->nInterfaceId);
307void igmp_router_ProcessGroupMembershipTimer()
309 NETSIM_ID d = pstruEventDetails->nDeviceId;
310 NETSIM_IPAddress group = pstruEventDetails->szOtherDetails;
312 ptrIGMP_VAR igmp = GET_IGMP_VAR(d);
314 ptrIGMP_ROUTER_DB db = router_get_multicast_db(d, group);
316 if (pstruEventDetails->dEventTime >=
318 igmp->GroupMembershipInterval*0.1*SECOND)
321 print_igmp_log(
"\nRouter %d, Time %0.0lf: Group membership timer expires for group addr %s. Deleting from database.",
323 pstruEventDetails->dEventTime,
325 router_delete_multicast_db(d, db);
330 print_igmp_log(
"\nRouter %d, Time %0.0lf: Refreshing Group membership timer for group addr %s.",
332 pstruEventDetails->dEventTime,
335 pstruEventDetails->dEventTime = db->reportRcvTime +
336 igmp->GroupMembershipInterval*0.1*SECOND;
337 fnpAddEvent(pstruEventDetails);
341void router_free(NETSIM_ID d)
343 ptrIGMP_ROUTER r = GET_IGMP_ROUTER(d);
344 ptrIGMP_ROUTER_DB db = r->database;
350 SET_IGMP_ROUTER(d, NULL);