diff options
| author | David Malone <dwmalone@FreeBSD.org> | 2007-05-18 15:05:49 +0000 |
|---|---|---|
| committer | David Malone <dwmalone@FreeBSD.org> | 2007-05-18 15:05:49 +0000 |
| commit | 34fa9e8a375677e49ed292438850cc93de636d4e (patch) | |
| tree | dea82612d4b2efca8b5cf91197d44d93d7a2f94c /sys | |
| parent | da7d0d1e2455bf20ff5d97c472961434ded06c54 (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/netgraph/ng_fec.c | 79 |
1 files changed, 77 insertions, 2 deletions
diff --git a/sys/netgraph/ng_fec.c b/sys/netgraph/ng_fec.c index ccd3c848f119..58f16a942d7f 100644 --- a/sys/netgraph/ng_fec.c +++ b/sys/netgraph/ng_fec.c @@ -149,9 +149,15 @@ struct ng_fec_portlist { int fec_idx; int fec_ifstat; struct ether_addr fec_mac; + SLIST_HEAD(__mclhd, ng_fec_mc) fec_mc_head; TAILQ_ENTRY(ng_fec_portlist) fec_list; }; +struct ng_fec_mc { + struct ifmultiaddr *mc_ifma; + SLIST_ENTRY(ng_fec_mc) mc_entries; +}; + struct ng_fec_bundle { TAILQ_HEAD(,ng_fec_portlist) ng_fec_ports; int fec_ifcnt; @@ -195,6 +201,7 @@ static int ng_fec_output(struct ifnet *ifp, struct mbuf *m0, static void ng_fec_tick(void *arg); static int ng_fec_addport(struct ng_fec_private *priv, char *iface); static int ng_fec_delport(struct ng_fec_private *priv, char *iface); +static int ng_fec_ether_cmdmulti(struct ifnet *trifp, struct ng_fec_portlist *p, int set); #ifdef DEBUG static void ng_fec_print_ioctl(struct ifnet *ifp, int cmd, caddr_t data); @@ -417,6 +424,9 @@ ng_fec_addport(struct ng_fec_private *priv, char *iface) new->fec_idx = b->fec_ifcnt; b->fec_ifcnt++; + /* Initialise the list of multicast addresses that we own. */ + SLIST_INIT(&new->fec_mc_head); + /* Save the real MAC address. */ bcopy(IF_LLADDR(bifp), (char *)&new->fec_mac, ETHER_ADDR_LEN); @@ -439,6 +449,9 @@ ng_fec_addport(struct ng_fec_private *priv, char *iface) new->fec_ifstat = -1; TAILQ_INSERT_TAIL(&b->ng_fec_ports, new, fec_list); + /* Add multicast addresses to this port. */ + ng_fec_ether_cmdmulti(ifp, new, 1); + return(0); } @@ -507,9 +520,70 @@ ng_fec_delport(struct ng_fec_private *priv, char *iface) return(0); } +static int +ng_fec_ether_cmdmulti(struct ifnet *trifp, struct ng_fec_portlist *p, int set) +{ + struct ifnet *ifp = p->fec_if; + struct ng_fec_mc *mc; + struct ifmultiaddr *ifma, *rifma = NULL; + struct sockaddr_dl sdl; + int error; + + bzero((char *)&sdl, sizeof(sdl)); + sdl.sdl_len = sizeof(sdl); + sdl.sdl_family = AF_LINK; + sdl.sdl_type = IFT_ETHER; + sdl.sdl_alen = ETHER_ADDR_LEN; + sdl.sdl_index = ifp->if_index; + + if (set) { + TAILQ_FOREACH(ifma, &trifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), + LLADDR(&sdl), ETHER_ADDR_LEN); + + error = if_addmulti(ifp, (struct sockaddr *)&sdl, &rifma); + if (error) + return (error); + mc = malloc(sizeof(struct ng_fec_mc), M_DEVBUF, M_NOWAIT); + if (mc == NULL) + return (ENOMEM); + mc->mc_ifma = rifma; + SLIST_INSERT_HEAD(&p->fec_mc_head, mc, mc_entries); + } + } else { + while ((mc = SLIST_FIRST(&p->fec_mc_head)) != NULL) { + SLIST_REMOVE(&p->fec_mc_head, mc, ng_fec_mc, mc_entries); + if_delmulti_ifma(mc->mc_ifma); + free(mc, M_DEVBUF); + } + } + return (0); +} + +static int +ng_fec_ether_setmulti(struct ifnet *ifp) +{ + struct ng_fec_private *priv; + struct ng_fec_bundle *b; + struct ng_fec_portlist *p; + + priv = ifp->if_softc; + b = &priv->fec_bundle; + + TAILQ_FOREACH(p, &b->ng_fec_ports, fec_list) { + /* First, remove any existing filter entries. */ + ng_fec_ether_cmdmulti(ifp, p, 0); + /* copy all addresses from the fec interface to the port */ + ng_fec_ether_cmdmulti(ifp, p, 1); + } + return (0); +} + /* * Pass an ioctl command down to all the underyling interfaces in a - * bundle. Used for setting multicast filters and flags. + * bundle. Used for setting flags. */ static int @@ -752,7 +826,7 @@ ng_fec_ioctl(struct ifnet *ifp, u_long command, caddr_t data) case SIOCADDMULTI: case SIOCDELMULTI: - ng_fec_setport(ifp, command, data); + ng_fec_ether_setmulti(ifp); error = 0; break; case SIOCGIFMEDIA: @@ -1255,6 +1329,7 @@ ng_fec_shutdown(node_p node) while (!TAILQ_EMPTY(&b->ng_fec_ports)) { p = TAILQ_FIRST(&b->ng_fec_ports); + ng_fec_ether_cmdmulti(priv->ifp, p, 0); ng_fec_delport(priv, p->fec_if->if_xname); } |
