openbsd-ports/net/igmpproxy/patches/patch-rttable_c

387 lines
14 KiB
Plaintext
Raw Normal View History

$OpenBSD: patch-rttable_c,v 1.1.1.1 2008/02/08 19:30:52 sthen Exp $
--- rttable.c.orig Sat Aug 20 13:46:20 2005
+++ rttable.c Mon Nov 19 12:56:50 2007
@@ -38,15 +38,22 @@
*/
#include "defs.h"
+#include <sys/queue.h>
/**
* Routing table structure definition. Double linked list...
*/
+struct Origin {
+ TAILQ_ENTRY(Origin) next;
+ uint32 originAddr;
+ int flood;
+ uint32 pktcnt;
+};
+
struct RouteTable {
struct RouteTable *nextroute; // Pointer to the next group in line.
struct RouteTable *prevroute; // Pointer to the previous group in line.
uint32 group; // The group to route
- uint32 originAddr; // The origin adress (only set on activated routes)
uint32 vifBits; // Bits representing recieving VIFs.
// Keeps the upstream membership state...
@@ -56,6 +63,7 @@ struct RouteTable {
uint32 ageVifBits; // Bits representing aging VIFs.
int ageValue; // Downcounter for death.
int ageActivity; // Records any acitivity that notes there are still listeners.
+ TAILQ_HEAD(originhead, Origin) originList; // The origin adresses (non-empty on activated routes)
};
@@ -65,19 +73,17 @@ static struct RouteTable *routing_table;
// Prototypes
void logRouteTable(char *header);
int internAgeRoute(struct RouteTable* croute);
+int internUpdateKernelRoute(struct RouteTable *route, int activate, struct Origin *o);
-// Socket for sending join or leave requests.
-int mcGroupSock = 0;
-
/**
* Function for retrieving the Multicast Group socket.
*/
int getMcGroupSock() {
- if( ! mcGroupSock ) {
- mcGroupSock = openUdpSocket( INADDR_ANY, 0 );;
+ if (MRouterFD < 0) {
+ log(LOG_ERR, errno, "no MRouterFD.");
}
- return mcGroupSock;
+ return MRouterFD;
}
/**
@@ -91,7 +97,7 @@ void initRouteTable() {
routing_table = NULL;
// Join the all routers group on downstream vifs...
- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
// If this is a downstream vif, we should join the All routers group...
if( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) && Dp->state == IF_STATE_DOWNSTREAM) {
IF_DEBUG log(LOG_DEBUG, 0, "Joining all-routers group %s on vif %s",
@@ -160,6 +166,7 @@ void sendJoinLeaveUpstream(struct RouteTable* route, i
*/
void clearAllRoutes() {
struct RouteTable *croute, *remainroute;
+ struct Origin *o;
// Loop through all routes...
for(croute = routing_table; croute; croute = remainroute) {
@@ -171,7 +178,7 @@ void clearAllRoutes() {
inetFmt(croute->group, s1));
// Uninstall current route
- if(!internUpdateKernelRoute(croute, 0)) {
+ if(!internUpdateKernelRoute(croute, 0, NULL)) {
log(LOG_WARNING, 0, "The removal from Kernel failed.");
}
@@ -179,6 +186,10 @@ void clearAllRoutes() {
sendJoinLeaveUpstream(croute, 0);
// Clear memory, and set pointer to next route...
+ while ((o = TAILQ_FIRST(&croute->originList))) {
+ TAILQ_REMOVE(&croute->originList, o, next);
+ free(o);
+ }
free(croute);
}
routing_table = NULL;
@@ -212,7 +223,6 @@ int insertRoute(uint32 group, int ifx) {
struct Config *conf = getCommonConfig();
struct RouteTable* croute;
- int result = 1;
// Sanitycheck the group adress...
if( ! IN_MULTICAST( ntohl(group) )) {
@@ -241,7 +251,8 @@ int insertRoute(uint32 group, int ifx) {
newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable));
// Insert the route desc and clear all pointers...
newroute->group = group;
- newroute->originAddr = 0;
+ TAILQ_INIT(&newroute->originList);
+
newroute->nextroute = NULL;
newroute->prevroute = NULL;
@@ -325,10 +336,10 @@ int insertRoute(uint32 group, int ifx) {
inetFmt(croute->group, s1), ifx);
// If the route is active, it must be reloaded into the Kernel..
- if(croute->originAddr != 0) {
+ if(!TAILQ_EMPTY(&croute->originList)) {
// Update route in kernel...
- if(!internUpdateKernelRoute(croute, 1)) {
+ if(!internUpdateKernelRoute(croute, 1, NULL)) {
log(LOG_WARNING, 0, "The insertion into Kernel failed.");
return 0;
}
@@ -351,7 +362,7 @@ int insertRoute(uint32 group, int ifx) {
* activated, it's reinstalled in the kernel. If
* the route is activated, no originAddr is needed.
*/
-int activateRoute(uint32 group, uint32 originAddr) {
+int activateRoute(uint32 group, uint32 originAddr, int downIf) {
struct RouteTable* croute;
int result = 0;
@@ -369,21 +380,42 @@ int activateRoute(uint32 group, uint32 originAddr) {
}
if(croute != NULL) {
+ struct Origin *o = NULL;
+ int found = 0;
+
// If the origin address is set, update the route data.
- if(originAddr > 0) {
- if(croute->originAddr > 0 && croute->originAddr!=originAddr) {
- log(LOG_WARNING, 0, "The origin for route %s changed from %s to %s",
- inetFmt(croute->group, s1),
- inetFmt(croute->originAddr, s2),
- inetFmt(originAddr, s3));
- }
- croute->originAddr = originAddr;
- }
+ if(originAddr > 0) {
- // Only update kernel table if there are listeners !
- if(croute->vifBits > 0) {
- result = internUpdateKernelRoute(croute, 1);
- }
+ TAILQ_FOREACH(o, &croute->originList, next) {
+ log(LOG_INFO, 0, "Origin for route %s have %s, new %s",
+ inetFmt(croute->group, s1),
+ inetFmt(o->originAddr, s2),
+ inetFmt(originAddr, s3));
+ if (o->originAddr==originAddr) {
+ found++;
+ break;
+ }
+ }
+ if (!found) {
+ log(LOG_NOTICE, 0, "New origin for route %s is %s, flood %d",
+ inetFmt(croute->group, s1),
+ inetFmt(originAddr, s3), downIf);
+ o = malloc(sizeof(*o));
+ o->originAddr = originAddr;
+ o->flood = downIf;
+ o->pktcnt = 0;
+ TAILQ_INSERT_TAIL(&croute->originList, o, next);
+ } else {
+ log(LOG_INFO, 0, "Have origin for route %s at %s, pktcnt %d",
+ inetFmt(croute->group, s1),
+ inetFmt(o->originAddr, s3),
+ o->pktcnt);
+ }
+ }
+
+ // Only update kernel table if there are listeners, but flood upstream!
+ if(croute->vifBits > 0 || downIf >= 0)
+ result = internUpdateKernelRoute(croute, 1, o);
}
IF_DEBUG logRouteTable("Activate Route");
@@ -443,7 +475,6 @@ void setRouteLastMemberMode(uint32 group) {
* route is not found, or not in this state, 0 is returned.
*/
int lastMemberGroupAge(uint32 group) {
- struct Config *conf = getCommonConfig();
struct RouteTable *croute;
croute = findRoute(group);
@@ -463,6 +494,7 @@ int lastMemberGroupAge(uint32 group) {
*/
int removeRoute(struct RouteTable* croute) {
struct Config *conf = getCommonConfig();
+ struct Origin *o;
int result = 1;
// If croute is null, no routes was found.
@@ -477,7 +509,7 @@ int removeRoute(struct RouteTable* croute) {
//BIT_ZERO(croute->vifBits);
// Uninstall current route from kernel
- if(!internUpdateKernelRoute(croute, 0)) {
+ if(!internUpdateKernelRoute(croute, 0, NULL)) {
log(LOG_WARNING, 0, "The removal from Kernel failed.");
result = 0;
}
@@ -503,7 +535,12 @@ int removeRoute(struct RouteTable* croute) {
croute->nextroute->prevroute = croute->prevroute;
}
}
+
// Free the memory, and set the route to NULL...
+ while ((o = TAILQ_FIRST(&croute->originList))) {
+ TAILQ_REMOVE(&croute->originList, o, next);
+ free(o);
+ }
free(croute);
croute = NULL;
@@ -551,6 +588,36 @@ int internAgeRoute(struct RouteTable* croute) {
}
}
+ {
+ struct Origin *o, *nxt;
+ struct sioc_sg_req sg_req;
+
+ sg_req.grp.s_addr = croute->group;
+ for (o = TAILQ_FIRST(&croute->originList); o; o = nxt) {
+ nxt = TAILQ_NEXT(o, next);
+ sg_req.src.s_addr = o->originAddr;
+ if (ioctl(MRouterFD, SIOCGETSGCNT, (char *)&sg_req) < 0) {
+ log(LOG_WARNING, errno, "%s (%s %s)",
+ "age_table_entry: SIOCGETSGCNT failing for",
+ inetFmt(o->originAddr, s1),
+ inetFmt(croute->group, s2));
+ /* Make sure it gets deleted below */
+ sg_req.pktcnt = o->pktcnt;
+ }
+ log(LOG_DEBUG, 0, "Aging Origin %s Dst %s PktCnt %d -> %d",
+ inetFmt(o->originAddr, s1), inetFmt(croute->group, s2),
+ o->pktcnt, sg_req.pktcnt);
+ if (sg_req.pktcnt == o->pktcnt) {
+ /* no traffic, remove from kernel cache */
+ internUpdateKernelRoute(croute, 0, o);
+ TAILQ_REMOVE(&croute->originList, o, next);
+ free(o);
+ } else {
+ o->pktcnt = sg_req.pktcnt;
+ }
+ }
+ }
+
// If the aging counter has reached zero, its time for updating...
if(croute->ageValue == 0) {
// Check for activity in the aging process,
@@ -560,7 +627,7 @@ int internAgeRoute(struct RouteTable* croute) {
inetFmt(croute->group,s1));
// Just update the routing settings in kernel...
- internUpdateKernelRoute(croute, 1);
+ internUpdateKernelRoute(croute, 1, NULL);
// We append the activity counter to the age, and continue...
croute->ageValue = croute->ageActivity;
@@ -586,34 +653,58 @@ int internAgeRoute(struct RouteTable* croute) {
/**
* Updates the Kernel routing table. If activate is 1, the route
* is (re-)activated. If activate is false, the route is removed.
+* if 'origin' is given, only the route with 'origin' will be
+* updated, otherwise all MFC routes for the group will updated.
*/
-int internUpdateKernelRoute(struct RouteTable *route, int activate) {
+int internUpdateKernelRoute(struct RouteTable *route, int activate, struct Origin *origin) {
struct MRouteDesc mrDesc;
struct IfDesc *Dp;
unsigned Ix;
+ struct Origin *o;
- if(route->originAddr>0) {
+ if (TAILQ_EMPTY(&route->originList)) {
+ log(LOG_NOTICE, 0, "Route is not active. No kernel updates done.");
+ return 1;
+ }
+ TAILQ_FOREACH(o, &route->originList, next) {
+ if (origin && origin != o)
+ continue;
// Build route descriptor from table entry...
// Set the source address and group address...
mrDesc.McAdr.s_addr = route->group;
- mrDesc.OriginAdr.s_addr = route->originAddr;
+ mrDesc.OriginAdr.s_addr = o->originAddr;
// clear output interfaces
memset( mrDesc.TtlVc, 0, sizeof( mrDesc.TtlVc ) );
- IF_DEBUG log(LOG_DEBUG, 0, "Vif bits : 0x%08x", route->vifBits);
+ IF_DEBUG log(LOG_DEBUG, 0, "Origin %s Vif bits : 0x%08x", inetFmt(o->originAddr, s1), route->vifBits);
// Set the TTL's for the route descriptor...
- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
- if(Dp->state == IF_STATE_UPSTREAM) {
- //IF_DEBUG log(LOG_DEBUG, 0, "Identified VIF #%d as upstream.", Dp->index);
- mrDesc.InVif = Dp->index;
- }
- else if(BIT_TST(route->vifBits, Dp->index)) {
- IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", Dp->index, Dp->threshold);
- mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
- }
+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
+ if (o->flood >= 0) {
+ if(Ix == o->flood) {
+ IF_DEBUG log(LOG_DEBUG, 0, "Identified Input VIF #%d as DOWNSTREAM.", Dp->index);
+ mrDesc.InVif = Dp->index;
+ }
+ else if(Dp->state == IF_STATE_UPSTREAM) {
+ IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for UPSTREAM Vif %d to %d", Dp->index, Dp->threshold);
+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
+ }
+ else if(BIT_TST(route->vifBits, Dp->index)) {
+ IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for DOWNSTREAM Vif %d to %d", Dp->index, Dp->threshold);
+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
+ }
+ } else {
+ if(Dp->state == IF_STATE_UPSTREAM) {
+ IF_DEBUG log(LOG_DEBUG, 0, "Identified VIF #%d as upstream.", Dp->index);
+ mrDesc.InVif = Dp->index;
+ }
+ else if(BIT_TST(route->vifBits, Dp->index)) {
+ IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", Dp->index, Dp->threshold);
+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
+ }
+ }
}
// Do the actual Kernel route update...
@@ -625,9 +716,6 @@ int internUpdateKernelRoute(struct RouteTable *route,
// Delete the route from Kernel...
delMRoute( &mrDesc );
}
-
- } else {
- log(LOG_NOTICE, 0, "Route is not active. No kernel updates done.");
}
return 1;
@@ -647,16 +735,17 @@ void logRouteTable(char *header) {
log(LOG_DEBUG, 0, "No routes in table...");
} else {
do {
- /*
- log(LOG_DEBUG, 0, "#%d: Src: %s, Dst: %s, Age:%d, St: %s, Prev: 0x%08x, T: 0x%08x, Next: 0x%08x",
- rcount, inetFmt(croute->originAddr, s1), inetFmt(croute->group, s2),
- croute->ageValue,(croute->originAddr>0?"A":"I"),
- croute->prevroute, croute, croute->nextroute);
- */
- log(LOG_DEBUG, 0, "#%d: Src: %s, Dst: %s, Age:%d, St: %s, OutVifs: 0x%08x",
- rcount, inetFmt(croute->originAddr, s1), inetFmt(croute->group, s2),
- croute->ageValue,(croute->originAddr>0?"A":"I"),
- croute->vifBits);
+ log(LOG_DEBUG, 0, "#%d: Dst: %s, Age:%d, St: %s, OutVifs: 0x%08x",
+ rcount, inetFmt(croute->group, s2),
+ croute->ageValue,(TAILQ_EMPTY(&croute->originList)?"I":"A"),
+ croute->vifBits);
+ {
+ struct Origin *o;
+ TAILQ_FOREACH(o, &croute->originList, next) {
+ log(LOG_DEBUG, 0, "#%d: Origin: %s floodIf %d pktcnt %d",
+ rcount, inetFmt(o->originAddr, s1), o->flood, o->pktcnt);
+ }
+ }
croute = croute->nextroute;