Re: Don't link multicast records to the first address

2013-11-26 Thread Mike Belopuhov
On 22 November 2013 09:26, Martin Pieuchot mpieuc...@nolizard.org wrote:
 On 18/11/13(Mon) 11:43, Martin Pieuchot wrote:
 Diff below changes the way protocol multicast addresses are linked to
 an interface.

 Right now they are added to a list attached to the first protocol
 address of an interface.  That makes this address descriptor and
 its position in the global list special.  Plus in the IPv6 case,
 a special kludge is used to move multicast records from one
 address to another.

 So this diff reuse the design of the protocol agnostic struct ifaddr
 and adds a new list of multicast addresses, struct ifmaddr, to the
 interface descriptor.  It solves the problems described previously and
 as a bonus properly free the IPv4 multicast records of an interface
 when it is detached, thus plugging some more leaks.

 I tested it with a carp setup, I appreciate any multicast related
 tests.

 Here's an updated diff after recent header changes.


looks better, indeed.  OK mikeb

 Did anybody tested it?  Does it break one of your use cases?  Comments?




Re: Don't link multicast records to the first address

2013-11-22 Thread Martin Pieuchot
On 18/11/13(Mon) 11:43, Martin Pieuchot wrote:
 Diff below changes the way protocol multicast addresses are linked to
 an interface.
 
 Right now they are added to a list attached to the first protocol
 address of an interface.  That makes this address descriptor and 
 its position in the global list special.  Plus in the IPv6 case,
 a special kludge is used to move multicast records from one
 address to another.
 
 So this diff reuse the design of the protocol agnostic struct ifaddr
 and adds a new list of multicast addresses, struct ifmaddr, to the
 interface descriptor.  It solves the problems described previously and
 as a bonus properly free the IPv4 multicast records of an interface
 when it is detached, thus plugging some more leaks.
 
 I tested it with a carp setup, I appreciate any multicast related
 tests.

Here's an updated diff after recent header changes.

Did anybody tested it?  Does it break one of your use cases?  Comments?


Index: net/if.c
===
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.277
diff -u -p -r1.277 if.c
--- net/if.c19 Nov 2013 09:00:43 -  1.277
+++ net/if.c22 Nov 2013 08:17:11 -
@@ -437,8 +437,9 @@ if_attach(struct ifnet *ifp)
 void
 if_attach_common(struct ifnet *ifp)
 {
-
TAILQ_INIT(ifp-if_addrlist);
+   TAILQ_INIT(ifp-if_maddrlist);
+
ifp-if_addrhooks = malloc(sizeof(*ifp-if_addrhooks),
M_TEMP, M_WAITOK);
TAILQ_INIT(ifp-if_addrhooks);
Index: net/if_var.h
===
RCS file: /cvs/src/sys/net/if_var.h,v
retrieving revision 1.1
diff -u -p -r1.1 if_var.h
--- net/if_var.h21 Nov 2013 17:32:12 -  1.1
+++ net/if_var.h22 Nov 2013 08:17:11 -
@@ -123,6 +123,7 @@ struct ifnet {  /* and the 
entries */
TAILQ_ENTRY(ifnet) if_list; /* all struct ifnets are chained */
TAILQ_ENTRY(ifnet) if_txlist;   /* list of ifnets ready to tx */
TAILQ_HEAD(, ifaddr) if_addrlist; /* linked list of addresses per if */
+   TAILQ_HEAD(, ifmaddr) if_maddrlist; /* list of multicast records */
TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */
struct hook_desc_head *if_addrhooks; /* address change callbacks */
struct hook_desc_head *if_linkstatehooks; /* link change callbacks */
@@ -302,6 +303,16 @@ struct ifaddr_item {
struct ifaddr   *ifai_ifa;
struct ifaddr_item  *ifai_next;
u_intifai_rdomain;
+};
+
+/*
+ * Interface multicast address.
+ */
+struct ifmaddr {
+   struct sockaddr *ifma_addr; /* Protocol address */
+   struct ifnet*ifma_ifp;  /* Back pointer to ifnet */
+   unsigned int ifma_refcnt;   /* Count of references */
+   TAILQ_ENTRY(ifmaddr) ifma_list; /* Per-interface list */
 };
 
 /*
Index: netinet/igmp.c
===
RCS file: /cvs/src/sys/netinet/igmp.c,v
retrieving revision 1.35
diff -u -p -r1.35 igmp.c
--- netinet/igmp.c  18 Oct 2013 09:04:02 -  1.35
+++ netinet/igmp.c  22 Nov 2013 08:17:12 -
@@ -83,6 +83,7 @@
 #include sys/sysctl.h
 
 #include net/if.h
+#include net/if_var.h
 #include net/route.h
 
 #include netinet/in.h
@@ -193,6 +194,7 @@ igmp_input(struct mbuf *m, ...)
struct igmp *igmp;
int igmplen;
int minlen;
+   struct ifmaddr *ifma;
struct in_multi *inm;
struct router_info *rti;
struct in_ifaddr *ia;
@@ -266,7 +268,10 @@ igmp_input(struct mbuf *m, ...)
 * except those that are already running and those
 * that belong to a local group (224.0.0.X).
 */
-   IN_FOREACH_MULTI(ia, ifp, inm) {
+   TAILQ_FOREACH(ifma, ifp-if_maddrlist, ifma_list) {
+   if (ifma-ifma_addr-sa_family != AF_INET)
+   continue;
+   inm = ifmatoinm(ifma);
if (inm-inm_timer == 0 
!IN_LOCAL_GROUP(inm-inm_addr.s_addr)) {
inm-inm_state = IGMP_DELAYING_MEMBER;
@@ -294,7 +299,10 @@ igmp_input(struct mbuf *m, ...)
 * timers already running, check if they need to be
 * reset.
 */
-   IN_FOREACH_MULTI(ia, ifp, inm) {
+   TAILQ_FOREACH(ifma, ifp-if_maddrlist, ifma_list) {
+   if (ifma-ifma_addr-sa_family != AF_INET)
+   continue;
+   inm = ifmatoinm(ifma);
if (!IN_LOCAL_GROUP(inm-inm_addr.s_addr) 
   

Re: Don't link multicast records to the first address

2013-11-22 Thread Stuart Henderson
I tried the old version (I'm using igmpproxy on my firewall and have native 
multicast over pppoe), no problems, but I haven't carefully read the diff yet.



Re: Don't link multicast records to the first address

2013-11-19 Thread Martin Pieuchot
On 18/11/13(Mon) 12:54, Alexey E. Suslikov wrote:
 Martin Pieuchot mpieuchot at nolizard.org writes:
 
   at  at  -1803,8 +1651,12  at  at  in6_delmulti(struct in6_multi
 *in6m)
 
 snip
 
  +   s = splsoftnet();
  +   TAILQ_REMOVE(ifp-if_maddrlist, in6m-in6m_ifma, ifma_list);
  +   splx(s);
  +
  free(in6m, M_IPMADDR);
  }
  splx(s);
 
 this splx seems wrong.

Good catch!  Here's and updated version, that comes with more spl love.


Index: net/if.c
===
RCS file: /home/ncvs/src/sys/net/if.c,v
retrieving revision 1.277
diff -u -p -r1.277 if.c
--- net/if.c19 Nov 2013 09:00:43 -  1.277
+++ net/if.c19 Nov 2013 10:07:24 -
@@ -437,8 +437,9 @@ if_attach(struct ifnet *ifp)
 void
 if_attach_common(struct ifnet *ifp)
 {
-
TAILQ_INIT(ifp-if_addrlist);
+   TAILQ_INIT(ifp-if_maddrlist);
+
ifp-if_addrhooks = malloc(sizeof(*ifp-if_addrhooks),
M_TEMP, M_WAITOK);
TAILQ_INIT(ifp-if_addrhooks);
Index: net/if.h
===
RCS file: /home/ncvs/src/sys/net/if.h,v
retrieving revision 1.152
diff -u -p -r1.152 if.h
--- net/if.h9 Nov 2013 06:38:42 -   1.152
+++ net/if.h19 Nov 2013 10:07:24 -
@@ -262,6 +262,7 @@ struct ifnet {  /* and the 
entries */
TAILQ_ENTRY(ifnet) if_list; /* all struct ifnets are chained */
TAILQ_ENTRY(ifnet) if_txlist;   /* list of ifnets ready to tx */
TAILQ_HEAD(, ifaddr) if_addrlist; /* linked list of addresses per if */
+   TAILQ_HEAD(, ifmaddr) if_maddrlist; /* list of multicast records */
TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */
struct hook_desc_head *if_addrhooks; /* address change callbacks */
struct hook_desc_head *if_linkstatehooks; /* link change callbacks */
@@ -506,6 +507,16 @@ struct ifaddr_item {
struct ifaddr   *ifai_ifa;
struct ifaddr_item  *ifai_next;
u_intifai_rdomain;
+};
+
+/*
+ * Interface multicast address.
+ */
+struct ifmaddr {
+   struct sockaddr *ifma_addr; /* Protocol address */
+   struct ifnet*ifma_ifp;  /* Back pointer to ifnet */
+   unsigned int ifma_refcnt;   /* Count of references */
+   TAILQ_ENTRY(ifmaddr) ifma_list; /* Per-interface list */
 };
 
 /*
Index: netinet/igmp.c
===
RCS file: /home/ncvs/src/sys/netinet/igmp.c,v
retrieving revision 1.35
diff -u -p -r1.35 igmp.c
--- netinet/igmp.c  18 Oct 2013 09:04:02 -  1.35
+++ netinet/igmp.c  19 Nov 2013 10:07:24 -
@@ -193,6 +193,7 @@ igmp_input(struct mbuf *m, ...)
struct igmp *igmp;
int igmplen;
int minlen;
+   struct ifmaddr *ifma;
struct in_multi *inm;
struct router_info *rti;
struct in_ifaddr *ia;
@@ -266,7 +267,10 @@ igmp_input(struct mbuf *m, ...)
 * except those that are already running and those
 * that belong to a local group (224.0.0.X).
 */
-   IN_FOREACH_MULTI(ia, ifp, inm) {
+   TAILQ_FOREACH(ifma, ifp-if_maddrlist, ifma_list) {
+   if (ifma-ifma_addr-sa_family != AF_INET)
+   continue;
+   inm = ifmatoinm(ifma);
if (inm-inm_timer == 0 
!IN_LOCAL_GROUP(inm-inm_addr.s_addr)) {
inm-inm_state = IGMP_DELAYING_MEMBER;
@@ -294,7 +298,10 @@ igmp_input(struct mbuf *m, ...)
 * timers already running, check if they need to be
 * reset.
 */
-   IN_FOREACH_MULTI(ia, ifp, inm) {
+   TAILQ_FOREACH(ifma, ifp-if_maddrlist, ifma_list) {
+   if (ifma-ifma_addr-sa_family != AF_INET)
+   continue;
+   inm = ifmatoinm(ifma);
if (!IN_LOCAL_GROUP(inm-inm_addr.s_addr) 
(ip-ip_dst.s_addr == INADDR_ALLHOSTS_GROUP 
||
 ip-ip_dst.s_addr == 
inm-inm_addr.s_addr)) {
@@ -479,6 +486,8 @@ void
 igmp_leavegroup(struct in_multi *inm)
 {
 
+   int s = splsoftnet();
+
switch (inm-inm_state) {
case IGMP_DELAYING_MEMBER:
case IGMP_IDLE_MEMBER:
@@ -494,6 +503,7 @@ igmp_leavegroup(struct in_multi *inm)
case IGMP_SLEEPING_MEMBER:
break;
}
+   splx(s);
 }
 
 void
@@ -521,11 +531,14 @@ void
 igmp_checktimer(struct ifnet *ifp)
 {
struct in_multi *inm;
-   struct in_ifaddr 

Don't link multicast records to the first address

2013-11-18 Thread Martin Pieuchot
Diff below changes the way protocol multicast addresses are linked to
an interface.

Right now they are added to a list attached to the first protocol
address of an interface.  That makes this address descriptor and 
its position in the global list special.  Plus in the IPv6 case,
a special kludge is used to move multicast records from one
address to another.

So this diff reuse the design of the protocol agnostic struct ifaddr
and adds a new list of multicast addresses, struct ifmaddr, to the
interface descriptor.  It solves the problems described previously and
as a bonus properly free the IPv4 multicast records of an interface
when it is detached, thus plugging some more leaks.

I tested it with a carp setup, I appreciate any multicast related
tests.

Comments, ok?

Index: net/if.c
===
RCS file: /home/ncvs/src/sys/net/if.c,v
retrieving revision 1.275
diff -u -p -r1.275 if.c
--- net/if.c11 Nov 2013 09:15:34 -  1.275
+++ net/if.c18 Nov 2013 10:43:00 -
@@ -441,8 +441,9 @@ if_attach(struct ifnet *ifp)
 void
 if_attach_common(struct ifnet *ifp)
 {
-
TAILQ_INIT(ifp-if_addrlist);
+   TAILQ_INIT(ifp-if_maddrlist);
+
ifp-if_addrhooks = malloc(sizeof(*ifp-if_addrhooks),
M_TEMP, M_WAITOK);
TAILQ_INIT(ifp-if_addrhooks);
Index: net/if.h
===
RCS file: /home/ncvs/src/sys/net/if.h,v
retrieving revision 1.152
diff -u -p -r1.152 if.h
--- net/if.h9 Nov 2013 06:38:42 -   1.152
+++ net/if.h18 Nov 2013 10:43:00 -
@@ -262,6 +262,7 @@ struct ifnet {  /* and the 
entries */
TAILQ_ENTRY(ifnet) if_list; /* all struct ifnets are chained */
TAILQ_ENTRY(ifnet) if_txlist;   /* list of ifnets ready to tx */
TAILQ_HEAD(, ifaddr) if_addrlist; /* linked list of addresses per if */
+   TAILQ_HEAD(, ifmaddr) if_maddrlist; /* list of multicast records */
TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */
struct hook_desc_head *if_addrhooks; /* address change callbacks */
struct hook_desc_head *if_linkstatehooks; /* link change callbacks */
@@ -506,6 +507,16 @@ struct ifaddr_item {
struct ifaddr   *ifai_ifa;
struct ifaddr_item  *ifai_next;
u_intifai_rdomain;
+};
+
+/*
+ * Interface multicast address.
+ */
+struct ifmaddr {
+   struct sockaddr *ifma_addr; /* Protocol address */
+   struct ifnet*ifma_ifp;  /* Back pointer to ifnet */
+   unsigned int ifma_refcnt;   /* Count of references */
+   TAILQ_ENTRY(ifmaddr) ifma_list; /* Per-interface list */
 };
 
 /*
Index: netinet/igmp.c
===
RCS file: /home/ncvs/src/sys/netinet/igmp.c,v
retrieving revision 1.35
diff -u -p -r1.35 igmp.c
--- netinet/igmp.c  18 Oct 2013 09:04:02 -  1.35
+++ netinet/igmp.c  18 Nov 2013 10:43:00 -
@@ -193,6 +193,7 @@ igmp_input(struct mbuf *m, ...)
struct igmp *igmp;
int igmplen;
int minlen;
+   struct ifmaddr *ifma;
struct in_multi *inm;
struct router_info *rti;
struct in_ifaddr *ia;
@@ -266,7 +267,10 @@ igmp_input(struct mbuf *m, ...)
 * except those that are already running and those
 * that belong to a local group (224.0.0.X).
 */
-   IN_FOREACH_MULTI(ia, ifp, inm) {
+   TAILQ_FOREACH(ifma, ifp-if_maddrlist, ifma_list) {
+   if (ifma-ifma_addr-sa_family != AF_INET)
+   continue;
+   inm = ifmatoinm(ifma);
if (inm-inm_timer == 0 
!IN_LOCAL_GROUP(inm-inm_addr.s_addr)) {
inm-inm_state = IGMP_DELAYING_MEMBER;
@@ -294,7 +298,10 @@ igmp_input(struct mbuf *m, ...)
 * timers already running, check if they need to be
 * reset.
 */
-   IN_FOREACH_MULTI(ia, ifp, inm) {
+   TAILQ_FOREACH(ifma, ifp-if_maddrlist, ifma_list) {
+   if (ifma-ifma_addr-sa_family != AF_INET)
+   continue;
+   inm = ifmatoinm(ifma);
if (!IN_LOCAL_GROUP(inm-inm_addr.s_addr) 
(ip-ip_dst.s_addr == INADDR_ALLHOSTS_GROUP 
||
 ip-ip_dst.s_addr == 
inm-inm_addr.s_addr)) {
@@ -521,11 +528,14 @@ void
 igmp_checktimer(struct ifnet *ifp)
 {
struct in_multi *inm;
-   struct in_ifaddr *ia;
+   struct ifmaddr *ifma;
 

Re: Don't link multicast records to the first address

2013-11-18 Thread Alexey E. Suslikov
Martin Pieuchot mpieuchot at nolizard.org writes:

  at  at  -1803,8 +1651,12  at  at  in6_delmulti(struct in6_multi
*in6m)

snip

 + s = splsoftnet();
 + TAILQ_REMOVE(ifp-if_maddrlist, in6m-in6m_ifma, ifma_list);
 + splx(s);
 +
   free(in6m, M_IPMADDR);
   }
   splx(s);

this splx seems wrong.