250-fix_multiple_downlink_interfaces.patch 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. --- a/src/igmpproxy.h
  2. +++ b/src/igmpproxy.h
  3. @@ -251,6 +251,7 @@ int activateRoute(uint32_t group, uint32
  4. void ageActiveRoutes();
  5. void setRouteLastMemberMode(uint32_t group);
  6. int lastMemberGroupAge(uint32_t group);
  7. +int interfaceInRoute(int32_t group, int Ix);
  8. /* request.c
  9. */
  10. --- a/src/request.c
  11. +++ b/src/request.c
  12. @@ -41,10 +41,10 @@
  13. // Prototypes...
  14. void sendGroupSpecificMemberQuery(void *argument);
  15. -
  16. +
  17. typedef struct {
  18. uint32_t group;
  19. - uint32_t vifAddr;
  20. + // uint32_t vifAddr;
  21. short started;
  22. } GroupVifDesc;
  23. @@ -142,7 +142,7 @@ void acceptLeaveMessage(uint32_t src, ui
  24. // Call the group spesific membership querier...
  25. gvDesc->group = group;
  26. - gvDesc->vifAddr = sourceVif->InAdr.s_addr;
  27. + // gvDesc->vifAddr = sourceVif->InAdr.s_addr;
  28. gvDesc->started = 0;
  29. sendGroupSpecificMemberQuery(gvDesc);
  30. @@ -159,6 +159,9 @@ void acceptLeaveMessage(uint32_t src, ui
  31. */
  32. void sendGroupSpecificMemberQuery(void *argument) {
  33. struct Config *conf = getCommonConfig();
  34. + struct IfDesc *Dp;
  35. + struct RouteTable *croute;
  36. + int Ix;
  37. // Cast argument to correct type...
  38. GroupVifDesc *gvDesc = (GroupVifDesc*) argument;
  39. @@ -166,22 +169,38 @@ void sendGroupSpecificMemberQuery(void *
  40. if(gvDesc->started) {
  41. // If aging returns false, we don't do any further action...
  42. if(!lastMemberGroupAge(gvDesc->group)) {
  43. + // FIXME: Should we free gvDesc here?
  44. return;
  45. }
  46. } else {
  47. gvDesc->started = 1;
  48. }
  49. - // Send a group specific membership query...
  50. - sendIgmp(gvDesc->vifAddr, gvDesc->group,
  51. - IGMP_MEMBERSHIP_QUERY,
  52. - conf->lastMemberQueryInterval * IGMP_TIMER_SCALE,
  53. - gvDesc->group, 0);
  54. -
  55. - my_log(LOG_DEBUG, 0, "Sent membership query from %s to %s. Delay: %d",
  56. - inetFmt(gvDesc->vifAddr,s1), inetFmt(gvDesc->group,s2),
  57. - conf->lastMemberQueryInterval);
  58. -
  59. + /**
  60. + * FIXME: This loops through all interfaces the group is active on an sends queries.
  61. + * It might be better to send only a query on the interface the leave was accepted on and remove only that interface from the route.
  62. + */
  63. +
  64. + // Loop through all downstream interfaces
  65. + for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
  66. + if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
  67. + if(Dp->state == IF_STATE_DOWNSTREAM) {
  68. + // Is that interface used in the group?
  69. + if (interfaceInRoute(gvDesc->group ,Dp->index)) {
  70. +
  71. + // Send a group specific membership query...
  72. + sendIgmp(Dp->InAdr.s_addr, gvDesc->group,
  73. + IGMP_MEMBERSHIP_QUERY,
  74. + conf->lastMemberQueryInterval * IGMP_TIMER_SCALE,
  75. + gvDesc->group, 0);
  76. +
  77. + my_log(LOG_DEBUG, 0, "Sent membership query from %s to %s. Delay: %d",
  78. + inetFmt(Dp->InAdr.s_addr,s1), inetFmt(gvDesc->group,s2),
  79. + conf->lastMemberQueryInterval);
  80. + }
  81. + }
  82. + }
  83. + }
  84. // Set timeout for next round...
  85. timer_setTimer(conf->lastMemberQueryInterval, sendGroupSpecificMemberQuery, gvDesc);
  86. --- a/src/rttable.c
  87. +++ b/src/rttable.c
  88. @@ -428,6 +428,25 @@ void ageActiveRoutes() {
  89. }
  90. /**
  91. +* Counts the number of interfaces a given route is active on
  92. +*/
  93. +int numberOfInterfaces(struct RouteTable *croute) {
  94. + int Ix;
  95. + struct IfDesc *Dp;
  96. + int result = 0;
  97. + // Loop through all interfaces
  98. + for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
  99. + // If the interface is used by the route, increase counter
  100. + if(BIT_TST(croute->vifBits, Dp->index)) {
  101. + result++;
  102. + }
  103. + }
  104. + my_log(LOG_DEBUG, 0, "counted %d interfaces", result);
  105. + return result;
  106. +}
  107. +
  108. +
  109. +/**
  110. * Should be called when a leave message is recieved, to
  111. * mark a route for the last member probe state.
  112. */
  113. @@ -439,8 +458,11 @@ void setRouteLastMemberMode(uint32_t gro
  114. if(croute!=NULL) {
  115. // Check for fast leave mode...
  116. if(croute->upstrState == ROUTESTATE_JOINED && conf->fastUpstreamLeave) {
  117. - // Send a leave message right away..
  118. - sendJoinLeaveUpstream(croute, 0);
  119. + // Send a leave message right away only when the route has been active on only one interface
  120. + if (numberOfInterfaces(croute) <= 1) {
  121. + my_log(LOG_DEBUG, 0, "Leaving group %d now", group);
  122. + sendJoinLeaveUpstream(croute, 0);
  123. + }
  124. }
  125. // Set the routingstate to Last member check...
  126. croute->upstrState = ROUTESTATE_CHECK_LAST_MEMBER;
  127. @@ -677,3 +699,18 @@ void logRouteTable(char *header) {
  128. my_log(LOG_DEBUG, 0, "-----------------------------------------------------");
  129. }
  130. +
  131. +/**
  132. +* Returns true when the given group belongs to the given interface
  133. +*/
  134. +int interfaceInRoute(int32_t group, int Ix) {
  135. + struct RouteTable* croute;
  136. + croute = findRoute(group);
  137. + if (croute != NULL) {
  138. + my_log(LOG_DEBUG, 0, "Interface id %d is in group $d", Ix, group);
  139. + return BIT_TST(croute->vifBits, Ix);
  140. + } else {
  141. + return 0;
  142. + }
  143. +}
  144. +