On 15/01/16(Fri) 12:00, Martin Pieuchot wrote:
> One of the checks missing to have an unlocked forwarding path is related
> to multicast. We must ensure that the list of multicast groups attached
> to an ifp is not modified when the CPU processing a packet is traversing
> it.
>
> In order to prepare for such change the diff below introduces a new
> function to abstract the list traversal.
>
> It is a simple refactoring but multiples reviews are more than welcome
> at this stage of the release cycle.
>
> ok?
I'm still looking for reviews.
> Index: netinet/in.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/in.c,v
> retrieving revision 1.125
> diff -u -p -r1.125 in.c
> --- netinet/in.c 3 Dec 2015 21:57:59 -0000 1.125
> +++ netinet/in.c 15 Jan 2016 10:33:36 -0000
> @@ -880,6 +880,21 @@ in_delmulti(struct in_multi *inm)
> }
> }
>
> +/*
> + * Return 1 if the multicast group represented by ``ap'' has been
> + * joined by interface ``ifp'', 0 otherwise.
> + */
> +int
> +in_hasmulti(struct in_addr *ap, struct ifnet *ifp)
> +{
> + struct in_multi *inm;
> + int joined;
> +
> + IN_LOOKUP_MULTI(*ap, ifp, inm);
> + joined = (inm != NULL);
> +
> + return (joined);
> +}
>
> void
> in_ifdetach(struct ifnet *ifp)
> Index: netinet/in_var.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet/in_var.h,v
> retrieving revision 1.37
> diff -u -p -r1.37 in_var.h
> --- netinet/in_var.h 3 Dec 2015 21:57:59 -0000 1.37
> +++ netinet/in_var.h 15 Jan 2016 10:34:02 -0000
> @@ -154,6 +154,7 @@ int in_ifinit(struct ifnet *,
> struct in_ifaddr *, struct sockaddr_in *, int);
> struct in_multi *in_addmulti(struct in_addr *, struct ifnet *);
> void in_delmulti(struct in_multi *);
> +int in_hasmulti(struct in_addr *, struct ifnet *);
> void in_ifscrub(struct ifnet *, struct in_ifaddr *);
> int in_control(struct socket *, u_long, caddr_t, struct ifnet *);
> void in_prefixlen2mask(struct in_addr *, int);
> Index: netinet/ip_carp.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_carp.c,v
> retrieving revision 1.285
> diff -u -p -r1.285 ip_carp.c
> --- netinet/ip_carp.c 12 Jan 2016 09:22:01 -0000 1.285
> +++ netinet/ip_carp.c 15 Jan 2016 10:47:19 -0000
> @@ -1809,17 +1809,13 @@ carp_addr_updated(void *v)
>
> /* We received address changes from if_addrhooks callback */
> if (new_naddrs != sc->sc_naddrs || new_naddrs6 != sc->sc_naddrs6) {
> - struct in_addr mc_addr;
> - struct in_multi *inm;
>
> sc->sc_naddrs = new_naddrs;
> sc->sc_naddrs6 = new_naddrs6;
>
> /* Re-establish multicast membership removed by in_control */
> if (IN_MULTICAST(sc->sc_peer.s_addr)) {
> - mc_addr.s_addr = sc->sc_peer.s_addr;
> - IN_LOOKUP_MULTI(mc_addr, &sc->sc_if, inm);
> - if (inm == NULL) {
> + if (!in_hasmulti(&sc->sc_peer, &sc->sc_if)) {
> struct in_multi **imm =
> sc->sc_imo.imo_membership;
> u_int16_t maxmem =
> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.265
> diff -u -p -r1.265 ip_input.c
> --- netinet/ip_input.c 3 Dec 2015 21:11:53 -0000 1.265
> +++ netinet/ip_input.c 15 Jan 2016 10:34:30 -0000
> @@ -346,8 +346,6 @@ ipv4_input(struct mbuf *m)
> }
>
> if (IN_MULTICAST(ip->ip_dst.s_addr)) {
> - struct in_multi *inm;
> -
> /*
> * Make sure M_MCAST is set. It should theoretically
> * already be there, but let's play safe because upper
> @@ -402,8 +400,7 @@ ipv4_input(struct mbuf *m)
> * See if we belong to the destination multicast group on the
> * arrival interface.
> */
> - IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
> - if (inm == NULL) {
> + if (!in_hasmulti(&ip->ip_dst, ifp)) {
> ipstat.ips_notmember++;
> if (!IN_LOCAL_GROUP(ip->ip_dst.s_addr))
> ipstat.ips_cantforward++;
> Index: netinet/ip_output.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_output.c,v
> retrieving revision 1.316
> diff -u -p -r1.316 ip_output.c
> --- netinet/ip_output.c 13 Jan 2016 09:38:36 -0000 1.316
> +++ netinet/ip_output.c 15 Jan 2016 10:43:47 -0000
> @@ -241,7 +241,6 @@ reroute:
>
> if (IN_MULTICAST(ip->ip_dst.s_addr) ||
> (ip->ip_dst.s_addr == INADDR_BROADCAST)) {
> - struct in_multi *inm;
>
> m->m_flags |= (ip->ip_dst.s_addr == INADDR_BROADCAST) ?
> M_BCAST : M_MCAST;
> @@ -295,9 +294,8 @@ reroute:
> ip->ip_src = ia->ia_addr.sin_addr;
> }
>
> - IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
> - if (inm != NULL &&
> - (imo == NULL || imo->imo_loop)) {
> + if ((imo == NULL || imo->imo_loop) &&
> + in_hasmulti(&ip->ip_dst, ifp)) {
> /*
> * If we belong to the destination multicast group
> * on the outgoing interface, and the caller did not
> Index: netinet6/in6.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/in6.c,v
> retrieving revision 1.182
> diff -u -p -r1.182 in6.c
> --- netinet6/in6.c 22 Dec 2015 10:01:01 -0000 1.182
> +++ netinet6/in6.c 15 Jan 2016 10:43:04 -0000
> @@ -1378,6 +1378,22 @@ in6_delmulti(struct in6_multi *in6m)
> }
> }
>
> +/*
> + * Return 1 if the multicast group represented by ``maddr6'' has been
> + * joined by interface ``ifp'', 0 otherwise.
> + */
> +int
> +in6_hasmulti(struct in6_addr *maddr6, struct ifnet *ifp)
> +{
> + struct in6_multi *in6m;
> + int joined;
> +
> + IN6_LOOKUP_MULTI(*maddr6, ifp, in6m);
> + joined = (in6m != NULL);
> +
> + return (joined);
> +}
> +
> struct in6_multi_mship *
> in6_joingroup(struct ifnet *ifp, struct in6_addr *addr, int *errorp)
> {
> Index: netinet6/in6_var.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/in6_var.h,v
> retrieving revision 1.58
> diff -u -p -r1.58 in6_var.h
> --- netinet6/in6_var.h 18 Nov 2015 13:58:02 -0000 1.58
> +++ netinet6/in6_var.h 15 Jan 2016 10:37:33 -0000
> @@ -495,6 +495,7 @@ do {
> \
>
> struct in6_multi *in6_addmulti(struct in6_addr *, struct ifnet *, int
> *);
> void in6_delmulti(struct in6_multi *);
> +int in6_hasmulti(struct in6_addr *, struct ifnet *);
> struct in6_multi_mship *in6_joingroup(struct ifnet *, struct in6_addr *, int
> *);
> int in6_leavegroup(struct in6_multi_mship *);
> int in6_control(struct socket *, u_long, caddr_t, struct ifnet *);
> Index: netinet6/ip6_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
> retrieving revision 1.153
> diff -u -p -r1.153 ip6_input.c
> --- netinet6/ip6_input.c 6 Jan 2016 10:02:42 -0000 1.153
> +++ netinet6/ip6_input.c 15 Jan 2016 10:39:08 -0000
> @@ -388,7 +388,6 @@ ip6_input(struct mbuf *m)
> * Multicast check
> */
> if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
> - struct in6_multi *in6m = NULL;
>
> /*
> * Make sure M_MCAST is set. It should theoretically
> @@ -401,8 +400,7 @@ ip6_input(struct mbuf *m)
> * See if we belong to the destination multicast group on the
> * arrival interface.
> */
> - IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
> - if (in6m)
> + if (in6_hasmulti(&ip6->ip6_dst, ifp))
> ours = 1;
> #ifdef MROUTING
> else if (!ip6_mforwarding || !ip6_mrouter)
> Index: netinet6/ip6_mroute.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_mroute.c,v
> retrieving revision 1.101
> diff -u -p -r1.101 ip6_mroute.c
> --- netinet6/ip6_mroute.c 3 Dec 2015 13:13:42 -0000 1.101
> +++ netinet6/ip6_mroute.c 15 Jan 2016 10:48:16 -0000
> @@ -1372,7 +1372,6 @@ phyint_send6(struct ip6_hdr *ip6, struct
> int error = 0;
> int s = splsoftnet();
> static struct route_in6 ro;
> - struct in6_multi *in6m;
> struct sockaddr_in6 *dst6;
>
> /*
> @@ -1416,8 +1415,7 @@ phyint_send6(struct ip6_hdr *ip6, struct
> * on the outgoing interface, loop back a copy.
> */
> dst6 = &ro.ro_dst;
> - IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
> - if (in6m != NULL) {
> + if (in6_hasmulti(&ip6->ip6_dst, ifp)) {
> dst6->sin6_len = sizeof(struct sockaddr_in6);
> dst6->sin6_family = AF_INET6;
> dst6->sin6_addr = ip6->ip6_dst;
> Index: netinet6/ip6_output.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
> retrieving revision 1.203
> diff -u -p -r1.203 ip6_output.c
> --- netinet6/ip6_output.c 13 Jan 2016 09:38:37 -0000 1.203
> +++ netinet6/ip6_output.c 15 Jan 2016 10:40:56 -0000
> @@ -566,7 +566,6 @@ reroute:
> m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */
> } else {
> /* Multicast */
> - struct in6_multi *in6m;
>
> m->m_flags = (m->m_flags & ~M_BCAST) | M_MCAST;
>
> @@ -579,9 +578,8 @@ reroute:
> goto bad;
> }
>
> - IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
> - if (in6m != NULL &&
> - (im6o == NULL || im6o->im6o_loop)) {
> + if ((im6o == NULL || im6o->im6o_loop) &&
> + in6_hasmulti(&ip6->ip6_dst, ifp)) {
> /*
> * If we belong to the destination multicast group
> * on the outgoing interface, and the caller did not
>