From 70dc8c3b4ad3bd171c68ba1645960241c5e9fd93 Mon Sep 17 00:00:00 2001 From: jhb Date: Tue, 5 Apr 2016 00:09:19 +0000 Subject: Remove an unneeded check. CPUs with valid per-CPU data are not absent. Sponsored by: Netflix --- sys/net/netisr.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sys/net') diff --git a/sys/net/netisr.c b/sys/net/netisr.c index 64efbd7..6b89a85 100644 --- a/sys/net/netisr.c +++ b/sys/net/netisr.c @@ -1167,9 +1167,6 @@ netisr_start(void *arg) STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) { if (nws_count >= netisr_maxthreads) break; - /* XXXRW: Is skipping absent CPUs still required here? */ - if (CPU_ABSENT(pc->pc_cpuid)) - continue; /* Worker will already be present for boot CPU. */ if (pc->pc_netisr != NULL) continue; -- cgit v1.1 From 1f8d2c0640ab54481001fa95f48cea15a460e121 Mon Sep 17 00:00:00 2001 From: rpokala Date: Wed, 6 Apr 2016 04:50:28 +0000 Subject: Storage Controller Interface driver - typo in unimplemented macro in scic_sds_controller_registers.h s/contoller/controller/ PR: 207336 Submitted by: Tony Narlock --- sys/net/if_lagg.c | 263 +++++++++++++++++++++++++++++++++++++++++++++++------- sys/net/if_lagg.h | 54 +++++++++-- 2 files changed, 278 insertions(+), 39 deletions(-) (limited to 'sys/net') diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 0477122..2f425a0 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -101,7 +101,11 @@ static const char laggname[] = "lagg"; static void lagg_lladdr(struct lagg_softc *, uint8_t *); static void lagg_capabilities(struct lagg_softc *); static void lagg_port_lladdr(struct lagg_port *, uint8_t *, lagg_llqtype); -static void lagg_port_setlladdr(void *, int); +static void lagg_port_ops(void *, int); +static void lagg_llq_action_mtu(struct lagg_softc *, + struct lagg_llq_slist_entry *); +static void lagg_llq_action_lladdr(struct lagg_softc *, + struct lagg_llq_slist_entry *); static int lagg_port_create(struct lagg_softc *, struct ifnet *); static int lagg_port_destroy(struct lagg_port *, int); static struct mbuf *lagg_input(struct ifnet *, struct mbuf *); @@ -130,6 +134,9 @@ static int lagg_media_change(struct ifnet *); static void lagg_media_status(struct ifnet *, struct ifmediareq *); static struct lagg_port *lagg_link_active(struct lagg_softc *, struct lagg_port *); +static int lagg_change_mtu(struct ifnet *, struct ifreq *); +static void _lagg_free_llq_entries(struct lagg_llq_slist_entry *); +static void lagg_free_llq_entries(struct lagg_softc *, lagg_llq_idx); /* Simple round robin */ static void lagg_rr_attach(struct lagg_softc *); @@ -165,6 +172,24 @@ static struct mbuf *lagg_lacp_input(struct lagg_softc *, struct lagg_port *, struct mbuf *); static void lagg_lacp_lladdr(struct lagg_softc *); +/* + * This action handler shall be called from taskqueue handler for each + * submitted operation + */ +typedef void (*lagg_llq_action)(struct lagg_softc *, + struct lagg_llq_slist_entry *); + +/* + * lagg llq action Table: Called at the taskqueue context for each + * submitted operations. + * Contents SHOULD be in sync with lagg_llq_idx index. + * New entries shall be appended. + */ +static const lagg_llq_action llq_action[LAGG_LLQ_MAX] = { + lagg_llq_action_lladdr, /* Maps to LAGG_LLQ_LLADDR index */ + lagg_llq_action_mtu, /* Maps to LAGG_LLQ_MTU index */ +}; + /* lagg protocol table */ static const struct lagg_proto { lagg_proto pr_num; @@ -487,7 +512,7 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params) LAGG_LOCK_INIT(sc); SLIST_INIT(&sc->sc_ports); - TASK_INIT(&sc->sc_lladdr_task, 0, lagg_port_setlladdr, sc); + TASK_INIT(&sc->sc_llq_task, 0, lagg_port_ops, sc); /* Initialise pseudo media types */ ifmedia_init(&sc->sc_media, 0, lagg_media_change, @@ -505,6 +530,10 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params) ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; ifp->if_capenable = ifp->if_capabilities = IFCAP_HWSTATS; + mtx_init(&sc->sc_mtu_ctxt.mtu_sync.lock, ifp->if_xname, + "mtu_sync_lock", MTX_DEF); + cv_init(&sc->sc_mtu_ctxt.mtu_sync.cv, "mtu_sync_cv"); + /* * Attach as an ordinary ethernet device, children will be attached * as special device IFT_IEEE8023ADLAG. @@ -553,7 +582,9 @@ lagg_clone_destroy(struct ifnet *ifp) SLIST_REMOVE(&V_lagg_list, sc, lagg_softc, sc_entries); LAGG_LIST_UNLOCK(); - taskqueue_drain(taskqueue_swi, &sc->sc_lladdr_task); + taskqueue_drain(taskqueue_swi, &sc->sc_llq_task); + cv_destroy(&sc->sc_mtu_ctxt.mtu_sync.cv); + mtx_destroy(&sc->sc_mtu_ctxt.mtu_sync.lock); LAGG_LOCK_DESTROY(sc); free(sc, M_DEVBUF); } @@ -645,7 +676,8 @@ lagg_port_lladdr(struct lagg_port *lp, uint8_t *lladdr, lagg_llqtype llq_type) { struct lagg_softc *sc = lp->lp_softc; struct ifnet *ifp = lp->lp_ifp; - struct lagg_llq *llq; + struct lagg_llq_slist_entry *cmn_llq; + struct lagg_lladdr_llq_ctxt *llq_ctxt; LAGG_WLOCK_ASSERT(sc); @@ -658,51 +690,213 @@ lagg_port_lladdr(struct lagg_port *lp, uint8_t *lladdr, lagg_llqtype llq_type) return; /* Check to make sure its not already queued to be changed */ - SLIST_FOREACH(llq, &sc->sc_llq_head, llq_entries) { - if (llq->llq_ifp == ifp) { + SLIST_FOREACH(cmn_llq, &sc->sc_llq[LAGG_LLQ_LLADDR], + llq_entries) { + llq_ctxt = (struct lagg_lladdr_llq_ctxt *)cmn_llq; + if (llq_ctxt->llq_ifp == ifp) { /* Update lladdr, it may have changed */ - bcopy(lladdr, llq->llq_lladdr, ETHER_ADDR_LEN); + bcopy(lladdr, llq_ctxt->llq_lladdr, ETHER_ADDR_LEN); return; } } - llq = malloc(sizeof(struct lagg_llq), M_DEVBUF, M_NOWAIT | M_ZERO); - if (llq == NULL) /* XXX what to do */ + llq_ctxt = malloc(sizeof(struct lagg_lladdr_llq_ctxt), M_DEVBUF, + M_NOWAIT | M_ZERO); + if (llq_ctxt == NULL) /* XXX what to do */ return; - llq->llq_ifp = ifp; - llq->llq_type = llq_type; - bcopy(lladdr, llq->llq_lladdr, ETHER_ADDR_LEN); + llq_ctxt->llq_ifp = ifp; + llq_ctxt->llq_type = llq_type; + bcopy(lladdr, llq_ctxt->llq_lladdr, ETHER_ADDR_LEN); /* XXX: We should insert to tail */ - SLIST_INSERT_HEAD(&sc->sc_llq_head, llq, llq_entries); + SLIST_INSERT_HEAD(&sc->sc_llq[LAGG_LLQ_LLADDR], + (struct lagg_llq_slist_entry *)llq_ctxt, llq_entries); - taskqueue_enqueue(taskqueue_swi, &sc->sc_lladdr_task); + taskqueue_enqueue(taskqueue_swi, &sc->sc_llq_task); } /* - * Set the interface MAC address from a taskqueue to avoid a LOR. + * Set the interface MTU, MAC address from a taskqueue to avoid a LOR. * * Set noinline to be dtrace-friendly */ static __noinline void -lagg_port_setlladdr(void *arg, int pending) +lagg_port_ops(void *arg, int pending) { struct lagg_softc *sc = (struct lagg_softc *)arg; - struct lagg_llq *llq, *head; - struct ifnet *ifp; + struct lagg_llq_slist_entry *llq_first; + lagg_llq_idx llq_idx; + + for (llq_idx = LAGG_LLQ_MIN; llq_idx < LAGG_LLQ_MAX; llq_idx++) { + LAGG_WLOCK(sc); + llq_first = SLIST_FIRST(&sc->sc_llq[llq_idx]); + SLIST_INIT(&sc->sc_llq[llq_idx]); + LAGG_WUNLOCK(sc); + + if (llq_first != NULL) + llq_action[llq_idx](sc, llq_first); + } +} - /* Grab a local reference of the queue and remove it from the softc */ +static void +lagg_llq_action_mtu(struct lagg_softc *sc, struct lagg_llq_slist_entry *first) +{ + struct lagg_llq_slist_entry *llq; + int err; + + /* Set the new MTU on the lagg interface */ LAGG_WLOCK(sc); - head = SLIST_FIRST(&sc->sc_llq_head); - SLIST_FIRST(&sc->sc_llq_head) = NULL; + sc->sc_ifp->if_mtu = ((struct lagg_mtu_llq_ctxt *)first)->llq_ifr.ifr_mtu; LAGG_WUNLOCK(sc); /* + * Traverse the queue and set the mtu on each ifp. It is safe to do + * unlocked as we have the only reference to it. + */ + err = EIO; /* In case the list is empty. */ + llq = first; + SLIST_FOREACH_FROM(llq, (struct __llqhd *)NULL, llq_entries) { + struct lagg_mtu_llq_ctxt *llq_ctxt; + + llq_ctxt = (struct lagg_mtu_llq_ctxt *)llq; + /* Set the new MTU on the physical interface */ + err = (*llq_ctxt->llq_ioctl)(llq_ctxt->llq_ifp, SIOCSIFMTU, + (caddr_t)&llq_ctxt->llq_ifr); + if (err) { + if_printf(llq_ctxt->llq_ifp, + "Failed to change MTU from %d to %d (err %d)\n", + llq_ctxt->llq_old_mtu, llq_ctxt->llq_ifr.ifr_mtu, err); + break; + } + } + + if (err) { + /* Restore the old MTU on the lagg interface */ + LAGG_WLOCK(sc); + sc->sc_ifp->if_mtu = ((struct lagg_mtu_llq_ctxt *)first)->llq_old_mtu; + LAGG_WUNLOCK(sc); + + /* Restore the old MTU on the physical interface */ + llq = first; + SLIST_FOREACH_FROM(llq, (struct __llqhd *)NULL, llq_entries) { + struct lagg_mtu_llq_ctxt *llq_ctxt; + + llq_ctxt = (struct lagg_mtu_llq_ctxt *)llq; + llq_ctxt->llq_ifr.ifr_mtu = llq_ctxt->llq_old_mtu; + err = (*llq_ctxt->llq_ioctl) + (llq_ctxt->llq_ifp, SIOCSIFMTU, (caddr_t)&llq_ctxt->llq_ifr); + if (err) { + if_printf(llq_ctxt->llq_ifp, + "Failed to restore MTU to %d (err %d)\n", + llq_ctxt->llq_old_mtu, err); + } + } + } + + /* Free the MTU LLQ entries */ + _lagg_free_llq_entries(first); + + mtx_lock(&sc->sc_mtu_ctxt.mtu_sync.lock); + sc->sc_mtu_ctxt.mtu_cmd_ret = err; + /* Signal for command completion */ + cv_signal(&sc->sc_mtu_ctxt.mtu_sync.cv); + mtx_unlock(&sc->sc_mtu_ctxt.mtu_sync.lock); +} + +static void +_lagg_free_llq_entries(struct lagg_llq_slist_entry *llq) +{ + struct lagg_llq_slist_entry *tmp_llq; + + SLIST_FOREACH_FROM_SAFE(llq, (struct __llqhd *)NULL, llq_entries, + tmp_llq) { + free(llq, M_DEVBUF); + } +} + +static void +lagg_free_llq_entries(struct lagg_softc *sc, lagg_llq_idx idx) +{ + struct lagg_llq_slist_entry *llq; + + LAGG_WLOCK_ASSERT(sc); + + llq = SLIST_FIRST(&sc->sc_llq[idx]); + SLIST_INIT(&sc->sc_llq[idx]); + + _lagg_free_llq_entries(llq); +} + +static int +lagg_change_mtu(struct ifnet *ifp, struct ifreq *ifr) +{ + struct lagg_softc *sc; + struct lagg_port *lp; + struct lagg_mtu_llq_ctxt *llq_ctxt; + int ret; + + sc = (struct lagg_softc *)ifp->if_softc; + ret = 0; + + LAGG_WLOCK(sc); + if (SLIST_EMPTY(&sc->sc_ports)) { + LAGG_WUNLOCK(sc); + return (EIO); + } else if (sc->sc_mtu_ctxt.busy) { + LAGG_WUNLOCK(sc); + return (EBUSY); + } else if (ifp->if_mtu == ifr->ifr_mtu) { + LAGG_WUNLOCK(sc); + return (0); + } + sc->sc_mtu_ctxt.busy = TRUE; + + SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + llq_ctxt = malloc(sizeof(struct lagg_mtu_llq_ctxt), M_DEVBUF, + M_NOWAIT); + if (llq_ctxt == NULL) { + lagg_free_llq_entries(sc, LAGG_LLQ_MTU); + ret = ENOMEM; + goto out; + } + SLIST_INSERT_HEAD(&sc->sc_llq[LAGG_LLQ_MTU], + (struct lagg_llq_slist_entry *)llq_ctxt, llq_entries); + + bcopy(ifr, &llq_ctxt->llq_ifr, sizeof(struct ifreq)); + llq_ctxt->llq_old_mtu = ifp->if_mtu; + llq_ctxt->llq_ifp = lp->lp_ifp; + llq_ctxt->llq_ioctl = lp->lp_ioctl; + } + mtx_lock(&sc->sc_mtu_ctxt.mtu_sync.lock); + taskqueue_enqueue(taskqueue_swi, &sc->sc_llq_task); + LAGG_WUNLOCK(sc); + + /* Wait for the command completion */ + cv_wait(&sc->sc_mtu_ctxt.mtu_sync.cv, &sc->sc_mtu_ctxt.mtu_sync.lock); + ret = sc->sc_mtu_ctxt.mtu_cmd_ret; + mtx_unlock(&sc->sc_mtu_ctxt.mtu_sync.lock); + LAGG_WLOCK(sc); + +out: + sc->sc_mtu_ctxt.busy = FALSE; + LAGG_WUNLOCK(sc); + return (ret); +} + +static void +lagg_llq_action_lladdr(struct lagg_softc *sc, struct lagg_llq_slist_entry *head) +{ + struct lagg_lladdr_llq_ctxt *llq_ctxt; + struct lagg_llq_slist_entry *llq; + struct ifnet *ifp; + + /* * Traverse the queue and set the lladdr on each ifp. It is safe to do * unlocked as we have the only reference to it. */ for (llq = head; llq != NULL; llq = head) { - ifp = llq->llq_ifp; + llq_ctxt = (struct lagg_lladdr_llq_ctxt *)llq; + ifp = llq_ctxt->llq_ifp; CURVNET_SET(ifp->if_vnet); @@ -711,9 +905,8 @@ lagg_port_setlladdr(void *arg, int pending) * Note that if_setlladdr() or iflladdr_event handler * may result in arp transmission / lltable updates. */ - if (llq->llq_type == LAGG_LLQTYPE_PHYS) - if_setlladdr(ifp, llq->llq_lladdr, - ETHER_ADDR_LEN); + if (llq_ctxt->llq_type == LAGG_LLQTYPE_PHYS) + if_setlladdr(ifp, llq_ctxt->llq_lladdr, ETHER_ADDR_LEN); else EVENTHANDLER_INVOKE(iflladdr_event, ifp); CURVNET_RESTORE(); @@ -877,7 +1070,8 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport) { struct lagg_softc *sc = lp->lp_softc; struct lagg_port *lp_ptr, *lp0; - struct lagg_llq *llq; + struct lagg_llq_slist_entry *cmn_llq; + struct lagg_lladdr_llq_ctxt *llq_ctxt; struct ifnet *ifp = lp->lp_ifp; uint64_t *pval, vdiff; int i; @@ -940,11 +1134,12 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport) /* Remove any pending lladdr changes from the queue */ if (lp->lp_detaching) { - SLIST_FOREACH(llq, &sc->sc_llq_head, llq_entries) { - if (llq->llq_ifp == ifp) { - SLIST_REMOVE(&sc->sc_llq_head, llq, lagg_llq, - llq_entries); - free(llq, M_DEVBUF); + SLIST_FOREACH(cmn_llq, &sc->sc_llq[LAGG_LLQ_LLADDR], llq_entries) { + llq_ctxt = (struct lagg_lladdr_llq_ctxt *)cmn_llq; + if (llq_ctxt->llq_ifp == ifp) { + SLIST_REMOVE(&sc->sc_llq[LAGG_LLQ_LLADDR], cmn_llq, + lagg_llq_slist_entry, llq_entries); + free(cmn_llq, M_DEVBUF); break; /* Only appears once */ } } @@ -1537,10 +1732,12 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCSIFCAP: - case SIOCSIFMTU: - /* Do not allow the MTU or caps to be directly changed */ + /* Do not allow the CAPs to be directly changed. */ error = EINVAL; break; + case SIOCSIFMTU: + error = lagg_change_mtu(ifp, ifr); + break; default: error = ether_ioctl(ifp, cmd, data); diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h index 334995e..11e9f2d 100644 --- a/sys/net/if_lagg.h +++ b/sys/net/if_lagg.h @@ -21,6 +21,8 @@ #ifndef _NET_LAGG_H #define _NET_LAGG_H +#include + /* * Global definitions */ @@ -207,18 +209,55 @@ typedef enum { LAGG_LLQTYPE_VIRT, /* Task related to lagg interface itself */ } lagg_llqtype; -/* List of interfaces to have the MAC address modified */ -struct lagg_llq { +/* Adding new entry here, SHOULD also have relevant entry in llq_action */ +typedef enum { + LAGG_LLQ_MIN = 0, + LAGG_LLQ_LLADDR = LAGG_LLQ_MIN, /* MAC Address index */ + LAGG_LLQ_MTU, /* MTU index */ + LAGG_LLQ_MAX /* This SHOULD be the last entry */ +} lagg_llq_idx; + +/* Common list entry definition for each taskq operation */ +struct lagg_llq_slist_entry { + SLIST_ENTRY(lagg_llq_slist_entry) llq_entries; +}; + +/* Context for lladdr llq operation part of lagg soft context */ +struct lagg_lladdr_llq_ctxt { + struct lagg_llq_slist_entry llq_cmn; /* This SHOULD be the first + member */ struct ifnet *llq_ifp; uint8_t llq_lladdr[ETHER_ADDR_LEN]; lagg_llqtype llq_type; - SLIST_ENTRY(lagg_llq) llq_entries; +}; + +/* Context for mtu llq operation part of lagg soft context */ +struct lagg_mtu_llq_ctxt { + struct lagg_llq_slist_entry llq_cmn; /* This SHOULD be the first + member */ + struct ifnet *llq_ifp; + struct ifreq llq_ifr; + uint32_t llq_old_mtu; + int (*llq_ioctl)(struct ifnet *, u_long, caddr_t); }; struct lagg_counters { uint64_t val[IFCOUNTERS]; }; +/* Conditional variables context for lagg operations */ +struct lagg_signal { + struct mtx lock; + struct cv cv; +}; + +/* Lagg MTU context */ +struct lagg_mtu_ctxt { + struct lagg_signal mtu_sync; /* Synchronize cmd completion */ + int mtu_cmd_ret; + bool busy; +}; + struct lagg_softc { struct ifnet *sc_ifp; /* virtual interface */ struct rmlock sc_mtx; @@ -236,9 +275,12 @@ struct lagg_softc { SLIST_HEAD(__tplhd, lagg_port) sc_ports; /* list of interfaces */ SLIST_ENTRY(lagg_softc) sc_entries; - struct task sc_lladdr_task; - SLIST_HEAD(__llqhd, lagg_llq) sc_llq_head; /* interfaces to program - the lladdr on */ + struct task sc_llq_task; /* SYNC & ASYNC ops + enqueued here */ + struct lagg_mtu_ctxt sc_mtu_ctxt; /* MTU programming */ + /* List of LLQs */ + SLIST_HEAD(__llqhd, lagg_llq_slist_entry) sc_llq[LAGG_LLQ_MAX]; + eventhandler_tag vlan_attach; eventhandler_tag vlan_detach; struct callout sc_callout; -- cgit v1.1 From b4cec75b570705bdb63d9d3d22ad0ca5269dd739 Mon Sep 17 00:00:00 2001 From: rpokala Date: Wed, 6 Apr 2016 04:58:20 +0000 Subject: Revert accidental submit of WIP as part of r297609 Pointyhat to: rpokala --- sys/net/if_lagg.c | 263 +++++++----------------------------------------------- sys/net/if_lagg.h | 54 ++--------- 2 files changed, 39 insertions(+), 278 deletions(-) (limited to 'sys/net') diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 2f425a0..0477122 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -101,11 +101,7 @@ static const char laggname[] = "lagg"; static void lagg_lladdr(struct lagg_softc *, uint8_t *); static void lagg_capabilities(struct lagg_softc *); static void lagg_port_lladdr(struct lagg_port *, uint8_t *, lagg_llqtype); -static void lagg_port_ops(void *, int); -static void lagg_llq_action_mtu(struct lagg_softc *, - struct lagg_llq_slist_entry *); -static void lagg_llq_action_lladdr(struct lagg_softc *, - struct lagg_llq_slist_entry *); +static void lagg_port_setlladdr(void *, int); static int lagg_port_create(struct lagg_softc *, struct ifnet *); static int lagg_port_destroy(struct lagg_port *, int); static struct mbuf *lagg_input(struct ifnet *, struct mbuf *); @@ -134,9 +130,6 @@ static int lagg_media_change(struct ifnet *); static void lagg_media_status(struct ifnet *, struct ifmediareq *); static struct lagg_port *lagg_link_active(struct lagg_softc *, struct lagg_port *); -static int lagg_change_mtu(struct ifnet *, struct ifreq *); -static void _lagg_free_llq_entries(struct lagg_llq_slist_entry *); -static void lagg_free_llq_entries(struct lagg_softc *, lagg_llq_idx); /* Simple round robin */ static void lagg_rr_attach(struct lagg_softc *); @@ -172,24 +165,6 @@ static struct mbuf *lagg_lacp_input(struct lagg_softc *, struct lagg_port *, struct mbuf *); static void lagg_lacp_lladdr(struct lagg_softc *); -/* - * This action handler shall be called from taskqueue handler for each - * submitted operation - */ -typedef void (*lagg_llq_action)(struct lagg_softc *, - struct lagg_llq_slist_entry *); - -/* - * lagg llq action Table: Called at the taskqueue context for each - * submitted operations. - * Contents SHOULD be in sync with lagg_llq_idx index. - * New entries shall be appended. - */ -static const lagg_llq_action llq_action[LAGG_LLQ_MAX] = { - lagg_llq_action_lladdr, /* Maps to LAGG_LLQ_LLADDR index */ - lagg_llq_action_mtu, /* Maps to LAGG_LLQ_MTU index */ -}; - /* lagg protocol table */ static const struct lagg_proto { lagg_proto pr_num; @@ -512,7 +487,7 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params) LAGG_LOCK_INIT(sc); SLIST_INIT(&sc->sc_ports); - TASK_INIT(&sc->sc_llq_task, 0, lagg_port_ops, sc); + TASK_INIT(&sc->sc_lladdr_task, 0, lagg_port_setlladdr, sc); /* Initialise pseudo media types */ ifmedia_init(&sc->sc_media, 0, lagg_media_change, @@ -530,10 +505,6 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params) ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; ifp->if_capenable = ifp->if_capabilities = IFCAP_HWSTATS; - mtx_init(&sc->sc_mtu_ctxt.mtu_sync.lock, ifp->if_xname, - "mtu_sync_lock", MTX_DEF); - cv_init(&sc->sc_mtu_ctxt.mtu_sync.cv, "mtu_sync_cv"); - /* * Attach as an ordinary ethernet device, children will be attached * as special device IFT_IEEE8023ADLAG. @@ -582,9 +553,7 @@ lagg_clone_destroy(struct ifnet *ifp) SLIST_REMOVE(&V_lagg_list, sc, lagg_softc, sc_entries); LAGG_LIST_UNLOCK(); - taskqueue_drain(taskqueue_swi, &sc->sc_llq_task); - cv_destroy(&sc->sc_mtu_ctxt.mtu_sync.cv); - mtx_destroy(&sc->sc_mtu_ctxt.mtu_sync.lock); + taskqueue_drain(taskqueue_swi, &sc->sc_lladdr_task); LAGG_LOCK_DESTROY(sc); free(sc, M_DEVBUF); } @@ -676,8 +645,7 @@ lagg_port_lladdr(struct lagg_port *lp, uint8_t *lladdr, lagg_llqtype llq_type) { struct lagg_softc *sc = lp->lp_softc; struct ifnet *ifp = lp->lp_ifp; - struct lagg_llq_slist_entry *cmn_llq; - struct lagg_lladdr_llq_ctxt *llq_ctxt; + struct lagg_llq *llq; LAGG_WLOCK_ASSERT(sc); @@ -690,213 +658,51 @@ lagg_port_lladdr(struct lagg_port *lp, uint8_t *lladdr, lagg_llqtype llq_type) return; /* Check to make sure its not already queued to be changed */ - SLIST_FOREACH(cmn_llq, &sc->sc_llq[LAGG_LLQ_LLADDR], - llq_entries) { - llq_ctxt = (struct lagg_lladdr_llq_ctxt *)cmn_llq; - if (llq_ctxt->llq_ifp == ifp) { + SLIST_FOREACH(llq, &sc->sc_llq_head, llq_entries) { + if (llq->llq_ifp == ifp) { /* Update lladdr, it may have changed */ - bcopy(lladdr, llq_ctxt->llq_lladdr, ETHER_ADDR_LEN); + bcopy(lladdr, llq->llq_lladdr, ETHER_ADDR_LEN); return; } } - llq_ctxt = malloc(sizeof(struct lagg_lladdr_llq_ctxt), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (llq_ctxt == NULL) /* XXX what to do */ + llq = malloc(sizeof(struct lagg_llq), M_DEVBUF, M_NOWAIT | M_ZERO); + if (llq == NULL) /* XXX what to do */ return; - llq_ctxt->llq_ifp = ifp; - llq_ctxt->llq_type = llq_type; - bcopy(lladdr, llq_ctxt->llq_lladdr, ETHER_ADDR_LEN); + llq->llq_ifp = ifp; + llq->llq_type = llq_type; + bcopy(lladdr, llq->llq_lladdr, ETHER_ADDR_LEN); /* XXX: We should insert to tail */ - SLIST_INSERT_HEAD(&sc->sc_llq[LAGG_LLQ_LLADDR], - (struct lagg_llq_slist_entry *)llq_ctxt, llq_entries); + SLIST_INSERT_HEAD(&sc->sc_llq_head, llq, llq_entries); - taskqueue_enqueue(taskqueue_swi, &sc->sc_llq_task); + taskqueue_enqueue(taskqueue_swi, &sc->sc_lladdr_task); } /* - * Set the interface MTU, MAC address from a taskqueue to avoid a LOR. + * Set the interface MAC address from a taskqueue to avoid a LOR. * * Set noinline to be dtrace-friendly */ static __noinline void -lagg_port_ops(void *arg, int pending) +lagg_port_setlladdr(void *arg, int pending) { struct lagg_softc *sc = (struct lagg_softc *)arg; - struct lagg_llq_slist_entry *llq_first; - lagg_llq_idx llq_idx; - - for (llq_idx = LAGG_LLQ_MIN; llq_idx < LAGG_LLQ_MAX; llq_idx++) { - LAGG_WLOCK(sc); - llq_first = SLIST_FIRST(&sc->sc_llq[llq_idx]); - SLIST_INIT(&sc->sc_llq[llq_idx]); - LAGG_WUNLOCK(sc); - - if (llq_first != NULL) - llq_action[llq_idx](sc, llq_first); - } -} - -static void -lagg_llq_action_mtu(struct lagg_softc *sc, struct lagg_llq_slist_entry *first) -{ - struct lagg_llq_slist_entry *llq; - int err; - - /* Set the new MTU on the lagg interface */ - LAGG_WLOCK(sc); - sc->sc_ifp->if_mtu = ((struct lagg_mtu_llq_ctxt *)first)->llq_ifr.ifr_mtu; - LAGG_WUNLOCK(sc); - - /* - * Traverse the queue and set the mtu on each ifp. It is safe to do - * unlocked as we have the only reference to it. - */ - err = EIO; /* In case the list is empty. */ - llq = first; - SLIST_FOREACH_FROM(llq, (struct __llqhd *)NULL, llq_entries) { - struct lagg_mtu_llq_ctxt *llq_ctxt; - - llq_ctxt = (struct lagg_mtu_llq_ctxt *)llq; - /* Set the new MTU on the physical interface */ - err = (*llq_ctxt->llq_ioctl)(llq_ctxt->llq_ifp, SIOCSIFMTU, - (caddr_t)&llq_ctxt->llq_ifr); - if (err) { - if_printf(llq_ctxt->llq_ifp, - "Failed to change MTU from %d to %d (err %d)\n", - llq_ctxt->llq_old_mtu, llq_ctxt->llq_ifr.ifr_mtu, err); - break; - } - } - - if (err) { - /* Restore the old MTU on the lagg interface */ - LAGG_WLOCK(sc); - sc->sc_ifp->if_mtu = ((struct lagg_mtu_llq_ctxt *)first)->llq_old_mtu; - LAGG_WUNLOCK(sc); - - /* Restore the old MTU on the physical interface */ - llq = first; - SLIST_FOREACH_FROM(llq, (struct __llqhd *)NULL, llq_entries) { - struct lagg_mtu_llq_ctxt *llq_ctxt; - - llq_ctxt = (struct lagg_mtu_llq_ctxt *)llq; - llq_ctxt->llq_ifr.ifr_mtu = llq_ctxt->llq_old_mtu; - err = (*llq_ctxt->llq_ioctl) - (llq_ctxt->llq_ifp, SIOCSIFMTU, (caddr_t)&llq_ctxt->llq_ifr); - if (err) { - if_printf(llq_ctxt->llq_ifp, - "Failed to restore MTU to %d (err %d)\n", - llq_ctxt->llq_old_mtu, err); - } - } - } - - /* Free the MTU LLQ entries */ - _lagg_free_llq_entries(first); - - mtx_lock(&sc->sc_mtu_ctxt.mtu_sync.lock); - sc->sc_mtu_ctxt.mtu_cmd_ret = err; - /* Signal for command completion */ - cv_signal(&sc->sc_mtu_ctxt.mtu_sync.cv); - mtx_unlock(&sc->sc_mtu_ctxt.mtu_sync.lock); -} - -static void -_lagg_free_llq_entries(struct lagg_llq_slist_entry *llq) -{ - struct lagg_llq_slist_entry *tmp_llq; - - SLIST_FOREACH_FROM_SAFE(llq, (struct __llqhd *)NULL, llq_entries, - tmp_llq) { - free(llq, M_DEVBUF); - } -} - -static void -lagg_free_llq_entries(struct lagg_softc *sc, lagg_llq_idx idx) -{ - struct lagg_llq_slist_entry *llq; - - LAGG_WLOCK_ASSERT(sc); - - llq = SLIST_FIRST(&sc->sc_llq[idx]); - SLIST_INIT(&sc->sc_llq[idx]); - - _lagg_free_llq_entries(llq); -} - -static int -lagg_change_mtu(struct ifnet *ifp, struct ifreq *ifr) -{ - struct lagg_softc *sc; - struct lagg_port *lp; - struct lagg_mtu_llq_ctxt *llq_ctxt; - int ret; - - sc = (struct lagg_softc *)ifp->if_softc; - ret = 0; - - LAGG_WLOCK(sc); - if (SLIST_EMPTY(&sc->sc_ports)) { - LAGG_WUNLOCK(sc); - return (EIO); - } else if (sc->sc_mtu_ctxt.busy) { - LAGG_WUNLOCK(sc); - return (EBUSY); - } else if (ifp->if_mtu == ifr->ifr_mtu) { - LAGG_WUNLOCK(sc); - return (0); - } - sc->sc_mtu_ctxt.busy = TRUE; - - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { - llq_ctxt = malloc(sizeof(struct lagg_mtu_llq_ctxt), M_DEVBUF, - M_NOWAIT); - if (llq_ctxt == NULL) { - lagg_free_llq_entries(sc, LAGG_LLQ_MTU); - ret = ENOMEM; - goto out; - } - SLIST_INSERT_HEAD(&sc->sc_llq[LAGG_LLQ_MTU], - (struct lagg_llq_slist_entry *)llq_ctxt, llq_entries); - - bcopy(ifr, &llq_ctxt->llq_ifr, sizeof(struct ifreq)); - llq_ctxt->llq_old_mtu = ifp->if_mtu; - llq_ctxt->llq_ifp = lp->lp_ifp; - llq_ctxt->llq_ioctl = lp->lp_ioctl; - } - mtx_lock(&sc->sc_mtu_ctxt.mtu_sync.lock); - taskqueue_enqueue(taskqueue_swi, &sc->sc_llq_task); - LAGG_WUNLOCK(sc); + struct lagg_llq *llq, *head; + struct ifnet *ifp; - /* Wait for the command completion */ - cv_wait(&sc->sc_mtu_ctxt.mtu_sync.cv, &sc->sc_mtu_ctxt.mtu_sync.lock); - ret = sc->sc_mtu_ctxt.mtu_cmd_ret; - mtx_unlock(&sc->sc_mtu_ctxt.mtu_sync.lock); + /* Grab a local reference of the queue and remove it from the softc */ LAGG_WLOCK(sc); - -out: - sc->sc_mtu_ctxt.busy = FALSE; + head = SLIST_FIRST(&sc->sc_llq_head); + SLIST_FIRST(&sc->sc_llq_head) = NULL; LAGG_WUNLOCK(sc); - return (ret); -} - -static void -lagg_llq_action_lladdr(struct lagg_softc *sc, struct lagg_llq_slist_entry *head) -{ - struct lagg_lladdr_llq_ctxt *llq_ctxt; - struct lagg_llq_slist_entry *llq; - struct ifnet *ifp; /* * Traverse the queue and set the lladdr on each ifp. It is safe to do * unlocked as we have the only reference to it. */ for (llq = head; llq != NULL; llq = head) { - llq_ctxt = (struct lagg_lladdr_llq_ctxt *)llq; - ifp = llq_ctxt->llq_ifp; + ifp = llq->llq_ifp; CURVNET_SET(ifp->if_vnet); @@ -905,8 +711,9 @@ lagg_llq_action_lladdr(struct lagg_softc *sc, struct lagg_llq_slist_entry *head) * Note that if_setlladdr() or iflladdr_event handler * may result in arp transmission / lltable updates. */ - if (llq_ctxt->llq_type == LAGG_LLQTYPE_PHYS) - if_setlladdr(ifp, llq_ctxt->llq_lladdr, ETHER_ADDR_LEN); + if (llq->llq_type == LAGG_LLQTYPE_PHYS) + if_setlladdr(ifp, llq->llq_lladdr, + ETHER_ADDR_LEN); else EVENTHANDLER_INVOKE(iflladdr_event, ifp); CURVNET_RESTORE(); @@ -1070,8 +877,7 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport) { struct lagg_softc *sc = lp->lp_softc; struct lagg_port *lp_ptr, *lp0; - struct lagg_llq_slist_entry *cmn_llq; - struct lagg_lladdr_llq_ctxt *llq_ctxt; + struct lagg_llq *llq; struct ifnet *ifp = lp->lp_ifp; uint64_t *pval, vdiff; int i; @@ -1134,12 +940,11 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport) /* Remove any pending lladdr changes from the queue */ if (lp->lp_detaching) { - SLIST_FOREACH(cmn_llq, &sc->sc_llq[LAGG_LLQ_LLADDR], llq_entries) { - llq_ctxt = (struct lagg_lladdr_llq_ctxt *)cmn_llq; - if (llq_ctxt->llq_ifp == ifp) { - SLIST_REMOVE(&sc->sc_llq[LAGG_LLQ_LLADDR], cmn_llq, - lagg_llq_slist_entry, llq_entries); - free(cmn_llq, M_DEVBUF); + SLIST_FOREACH(llq, &sc->sc_llq_head, llq_entries) { + if (llq->llq_ifp == ifp) { + SLIST_REMOVE(&sc->sc_llq_head, llq, lagg_llq, + llq_entries); + free(llq, M_DEVBUF); break; /* Only appears once */ } } @@ -1732,11 +1537,9 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCSIFCAP: - /* Do not allow the CAPs to be directly changed. */ - error = EINVAL; - break; case SIOCSIFMTU: - error = lagg_change_mtu(ifp, ifr); + /* Do not allow the MTU or caps to be directly changed */ + error = EINVAL; break; default: diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h index 11e9f2d..334995e 100644 --- a/sys/net/if_lagg.h +++ b/sys/net/if_lagg.h @@ -21,8 +21,6 @@ #ifndef _NET_LAGG_H #define _NET_LAGG_H -#include - /* * Global definitions */ @@ -209,55 +207,18 @@ typedef enum { LAGG_LLQTYPE_VIRT, /* Task related to lagg interface itself */ } lagg_llqtype; -/* Adding new entry here, SHOULD also have relevant entry in llq_action */ -typedef enum { - LAGG_LLQ_MIN = 0, - LAGG_LLQ_LLADDR = LAGG_LLQ_MIN, /* MAC Address index */ - LAGG_LLQ_MTU, /* MTU index */ - LAGG_LLQ_MAX /* This SHOULD be the last entry */ -} lagg_llq_idx; - -/* Common list entry definition for each taskq operation */ -struct lagg_llq_slist_entry { - SLIST_ENTRY(lagg_llq_slist_entry) llq_entries; -}; - -/* Context for lladdr llq operation part of lagg soft context */ -struct lagg_lladdr_llq_ctxt { - struct lagg_llq_slist_entry llq_cmn; /* This SHOULD be the first - member */ +/* List of interfaces to have the MAC address modified */ +struct lagg_llq { struct ifnet *llq_ifp; uint8_t llq_lladdr[ETHER_ADDR_LEN]; lagg_llqtype llq_type; -}; - -/* Context for mtu llq operation part of lagg soft context */ -struct lagg_mtu_llq_ctxt { - struct lagg_llq_slist_entry llq_cmn; /* This SHOULD be the first - member */ - struct ifnet *llq_ifp; - struct ifreq llq_ifr; - uint32_t llq_old_mtu; - int (*llq_ioctl)(struct ifnet *, u_long, caddr_t); + SLIST_ENTRY(lagg_llq) llq_entries; }; struct lagg_counters { uint64_t val[IFCOUNTERS]; }; -/* Conditional variables context for lagg operations */ -struct lagg_signal { - struct mtx lock; - struct cv cv; -}; - -/* Lagg MTU context */ -struct lagg_mtu_ctxt { - struct lagg_signal mtu_sync; /* Synchronize cmd completion */ - int mtu_cmd_ret; - bool busy; -}; - struct lagg_softc { struct ifnet *sc_ifp; /* virtual interface */ struct rmlock sc_mtx; @@ -275,12 +236,9 @@ struct lagg_softc { SLIST_HEAD(__tplhd, lagg_port) sc_ports; /* list of interfaces */ SLIST_ENTRY(lagg_softc) sc_entries; - struct task sc_llq_task; /* SYNC & ASYNC ops - enqueued here */ - struct lagg_mtu_ctxt sc_mtu_ctxt; /* MTU programming */ - /* List of LLQs */ - SLIST_HEAD(__llqhd, lagg_llq_slist_entry) sc_llq[LAGG_LLQ_MAX]; - + struct task sc_lladdr_task; + SLIST_HEAD(__llqhd, lagg_llq) sc_llq_head; /* interfaces to program + the lladdr on */ eventhandler_tag vlan_attach; eventhandler_tag vlan_detach; struct callout sc_callout; -- cgit v1.1 From b63211eed5e20b9ad1b7649373ab39eff72e2521 Mon Sep 17 00:00:00 2001 From: pfg Date: Sun, 10 Apr 2016 23:07:00 +0000 Subject: Cleanup unnecessary semicolons from the kernel. Found with devel/coccinelle. --- sys/net/if_gif.c | 2 +- sys/net/if_gre.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'sys/net') diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index 1607af9..cfa4650 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -1023,7 +1023,7 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst) #endif default: return (EAFNOSUPPORT); - }; + } if (sc->gif_family != src->sa_family) gif_detach(sc); diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index 9d4a976..425df8e 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -353,7 +353,7 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) if (error != 0) goto end; #endif - }; + } error = gre_set_tunnel(ifp, src, dst); break; case SIOCDIFPHYADDR: @@ -960,7 +960,7 @@ gre_transmit(struct ifnet *ifp, struct mbuf *m) default: m_freem(m); error = ENETDOWN; - }; + } drop: if (error) if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); -- cgit v1.1 From 146f54f44d1f0decdbae4e4abcff3ad6457c0ae2 Mon Sep 17 00:00:00 2001 From: bz Date: Mon, 11 Apr 2016 10:00:38 +0000 Subject: During if_vmove() we call if_detach_internal() which in turn calls the event handler notifying about interface departure and one of the consumers will detach if_bpf. There is no way for us to re-attach this easily as the DLT and hdrlen are only given on interface creation. Add a function to allow us to query the DLT and hdrlen from a current BPF attachment and after if_attach_internal() manually re-add the if_bpf attachment using these values. Found by panics triggered by nd6 packets running past BPF_MTAP() with no proper if_bpf pointer on the interface. Also add a basic DDB show function to investigate the if_bpf attachment of an interface. Reviewed by: gnn MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D5896 --- sys/net/bpf.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sys/net/bpf.h | 3 +++ sys/net/if.c | 11 +++++++++++ 3 files changed, 76 insertions(+) (limited to 'sys/net') diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 54dd184..5f2ef71 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include "opt_bpf.h" #include "opt_compat.h" +#include "opt_ddb.h" #include "opt_netgraph.h" #include @@ -67,6 +68,10 @@ __FBSDID("$FreeBSD$"); #include +#ifdef DDB +#include +#endif + #include #include #include @@ -2569,6 +2574,32 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp) if_printf(ifp, "bpf attached\n"); } +#ifdef VIMAGE +/* + * When moving interfaces between vnet instances we need a way to + * query the dlt and hdrlen before detach so we can re-attch the if_bpf + * after the vmove. We unfortunately have no device driver infrastructure + * to query the interface for these values after creation/attach, thus + * add this as a workaround. + */ +int +bpf_get_bp_params(struct bpf_if *bp, u_int *bif_dlt, u_int *bif_hdrlen) +{ + + if (bp == NULL) + return (ENXIO); + if (bif_dlt == NULL && bif_hdrlen == NULL) + return (0); + + if (bif_dlt != NULL) + *bif_dlt = bp->bif_dlt; + if (bif_hdrlen != NULL) + *bif_hdrlen = bp->bif_hdrlen; + + return (0); +} +#endif + /* * Detach bpf from an interface. This involves detaching each descriptor * associated with the interface. Notify each descriptor as it's detached @@ -2977,3 +3008,34 @@ bpf_validate(const struct bpf_insn *f, int len) } #endif /* !DEV_BPF && !NETGRAPH_BPF */ + +#ifdef DDB +static void +bpf_show_bpf_if(struct bpf_if *bpf_if) +{ + + if (bpf_if == NULL) + return; + db_printf("%p:\n", bpf_if); +#define BPF_DB_PRINTF(f, e) db_printf(" %s = " f "\n", #e, bpf_if->e); + /* bif_ext.bif_next */ + /* bif_ext.bif_dlist */ + BPF_DB_PRINTF("%#x", bif_dlt); + BPF_DB_PRINTF("%u", bif_hdrlen); + BPF_DB_PRINTF("%p", bif_ifp); + /* bif_lock */ + /* bif_wlist */ + BPF_DB_PRINTF("%#x", bif_flags); +} + +DB_SHOW_COMMAND(bpf_if, db_show_bpf_if) +{ + + if (!have_addr) { + db_printf("usage: show bpf_if \n"); + return; + } + + bpf_show_bpf_if((struct bpf_if *)addr); +} +#endif diff --git a/sys/net/bpf.h b/sys/net/bpf.h index a74b521..0ffc15ac 100644 --- a/sys/net/bpf.h +++ b/sys/net/bpf.h @@ -1469,6 +1469,9 @@ void bpf_mtap2(struct bpf_if *, void *, u_int, struct mbuf *); void bpfattach(struct ifnet *, u_int, u_int); void bpfattach2(struct ifnet *, u_int, u_int, struct bpf_if **); void bpfdetach(struct ifnet *); +#ifdef VIMAGE +int bpf_get_bp_params(struct bpf_if *, u_int *, u_int *); +#endif void bpfilterattach(int); u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int); diff --git a/sys/net/if.c b/sys/net/if.c index b9e524c..2c44c87 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1021,8 +1021,16 @@ void if_vmove(struct ifnet *ifp, struct vnet *new_vnet) { struct if_clone *ifc; + u_int bif_dlt, bif_hdrlen; int rc; + /* + * if_detach_internal() will call the eventhandler to notify + * interface departure. That will detach if_bpf. We need to + * safe the dlt and hdrlen so we can re-attach it later. + */ + bpf_get_bp_params(ifp->if_bpf, &bif_dlt, &bif_hdrlen); + /* * Detach from current vnet, but preserve LLADDR info, do not * mark as dead etc. so that the ifnet can be reattached later. @@ -1062,6 +1070,9 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet) if_attach_internal(ifp, 1, ifc); + if (ifp->if_bpf == NULL) + bpfattach(ifp, bif_dlt, bif_hdrlen); + CURVNET_RESTORE(); } -- cgit v1.1