Date: Mon, 15 Apr 2013 21:09:54 +0400 From: "Alexander V. Chernikov" <melifaro@FreeBSD.org> To: "freebsd-net@freebsd.org" <net@freebsd.org>, hackers@freebsd.org Cc: Jack Vogel <jfvogel@gmail.com> Subject: VLANHWFILTER "upgrade" Message-ID: <516C3462.30501@FreeBSD.org>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------000509050108030808090809 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Hello list. We currently have VLAHWFILTER functionality allowing underlying physical/virtual interfaces to be aware of vlans stacked on them. However, this knowledge is only used to program NIC hw filter (or to broadcast to member ifaces in lagg case). Proposed idea is to save vlan ifp pointer inside the driver and push packet to given vlan directly. This changes removes 1 read lock on RX fast path. Additionally, we can do the same in more popular case of ix -> lagg [ -> lagg -> lagg ] -> vlan if we solve 1) lagg interface counters issue (trivial) 2) IFF_MONITOR on lagg interface issue (not so trivial, unfortunately). Patch to ixgbe driver attached (maybe it is better to put ixgbe_vlan_get() and struct ifvlans directly to if_vlan.[ch]). -- WBR, Alexander --------------000509050108030808090809 Content-Type: text/plain; charset=UTF-8; name="ixgbe_vlans2.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="ixgbe_vlans2.diff" Index: sys/dev/ixgbe/ixgbe.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/dev/ixgbe/ixgbe.c (revision 248704) +++ sys/dev/ixgbe/ixgbe.c (working copy) @@ -2880,6 +2880,14 @@ ixgbe_allocate_queues(struct adapter *adapter) error =3D ENOMEM; goto err_rx_desc; } + + if ((rxr->vlans =3D malloc(sizeof(struct ifvlans), M_DEVBUF, + M_NOWAIT | M_ZERO)) =3D=3D NULL) { + device_printf(dev, + "Critical Failure setting up vlan index\n"); + error =3D ENOMEM; + goto err_rx_desc; + } } =20 /* @@ -4271,6 +4279,11 @@ ixgbe_free_receive_buffers(struct rx_ring *rxr) rxr->ptag =3D NULL; } =20 + if (rxr->vlans !=3D NULL) { + free(rxr->vlans, M_DEVBUF); + rxr->vlans =3D NULL; + } + return; } =20 @@ -4303,7 +4316,7 @@ ixgbe_rx_input(struct rx_ring *rxr, struct ifnet * return; } IXGBE_RX_UNLOCK(rxr); - (*ifp->if_input)(ifp, m); + (*ifp->if_input)(m->m_pkthdr.rcvif, m); IXGBE_RX_LOCK(rxr); } =20 @@ -4360,6 +4373,7 @@ ixgbe_rxeof(struct ix_queue *que) u16 count =3D rxr->process_limit; union ixgbe_adv_rx_desc *cur; struct ixgbe_rx_buf *rbuf, *nbuf; + struct ifnet *ifp_dst; =20 IXGBE_RX_LOCK(rxr); =20 @@ -4522,9 +4536,19 @@ ixgbe_rxeof(struct ix_queue *que) (staterr & IXGBE_RXD_STAT_VP)) vtag =3D le16toh(cur->wb.upper.vlan); if (vtag) { - sendmp->m_pkthdr.ether_vtag =3D vtag; - sendmp->m_flags |=3D M_VLANTAG; - } + ifp_dst =3D rxr->vlans->idx[EVL_VLANOFTAG(vtag)]; + + if (ifp_dst !=3D NULL) { + ifp_dst->if_ipackets++; + sendmp->m_pkthdr.rcvif =3D ifp_dst; + } else { + sendmp->m_pkthdr.ether_vtag =3D vtag; + sendmp->m_flags |=3D M_VLANTAG; + sendmp->m_pkthdr.rcvif =3D ifp; + } + } else + sendmp->m_pkthdr.rcvif =3D ifp; + if ((ifp->if_capenable & IFCAP_RXCSUM) !=3D 0) ixgbe_rx_checksum(staterr, sendmp, ptype); #if __FreeBSD_version >=3D 800000 @@ -4625,7 +4649,32 @@ ixgbe_rx_checksum(u32 staterr, struct mbuf * mp, u= return; } =20 +/* + * This routine gets real vlan ifp based on + * underlying ifp and vlan tag. + */ +static struct ifnet * +ixgbe_get_vlan(struct ifnet *ifp, uint16_t vtag) +{ =20 + /* XXX: IFF_MONITOR */ +#if 0 + struct lagg_port *lp =3D ifp->if_lagg; + struct lagg_softc *sc =3D lp->lp_softc; + + /* Skip lagg nesting */ + while (ifp->if_type =3D=3D IFT_IEEE8023ADLAG) { + lp =3D ifp->if_lagg; + sc =3D lp->lp_softc; + ifp =3D sc->sc_ifp; + } +#endif + /* Get vlan interface based on tag */ + ifp =3D VLAN_DEVAT(ifp, vtag); + + return (ifp); +} + /* ** This routine is run via an vlan config EVENT, ** it enables us to use the HW Filter table since @@ -4637,7 +4686,9 @@ static void ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) { struct adapter *adapter =3D ifp->if_softc; - u16 index, bit; + u16 index, bit, j; + struct rx_ring *rxr; + struct ifnet *ifv; =20 if (ifp->if_softc !=3D arg) /* Not our event */ return; @@ -4645,7 +4696,20 @@ ixgbe_register_vlan(void *arg, struct ifnet *ifp, if ((vtag =3D=3D 0) || (vtag > 4095)) /* Invalid */ return; =20 + ifv =3D ixgbe_get_vlan(ifp, vtag); + IXGBE_CORE_LOCK(adapter); + + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) { + rxr =3D adapter->rx_rings; + + for (j =3D 0; j < adapter->num_queues; j++, rxr++) { + IXGBE_RX_LOCK(rxr); + rxr->vlans->idx[vtag] =3D ifv; + IXGBE_RX_UNLOCK(rxr); + } + } + index =3D (vtag >> 5) & 0x7F; bit =3D vtag & 0x1F; adapter->shadow_vfta[index] |=3D (1 << bit); @@ -4663,7 +4727,8 @@ static void ixgbe_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) { struct adapter *adapter =3D ifp->if_softc; - u16 index, bit; + u16 index, bit, j; + struct rx_ring *rxr; =20 if (ifp->if_softc !=3D arg) return; @@ -4672,6 +4737,15 @@ ixgbe_unregister_vlan(void *arg, struct ifnet *ifp= return; =20 IXGBE_CORE_LOCK(adapter); + + rxr =3D adapter->rx_rings; + + for (j =3D 0; j < adapter->num_queues; j++, rxr++) { + IXGBE_RX_LOCK(rxr); + rxr->vlans->idx[vtag] =3D NULL; + IXGBE_RX_UNLOCK(rxr); + } + index =3D (vtag >> 5) & 0x7F; bit =3D vtag & 0x1F; adapter->shadow_vfta[index] &=3D ~(1 << bit); @@ -4686,8 +4760,8 @@ ixgbe_setup_vlan_hw_support(struct adapter *adapte { struct ifnet *ifp =3D adapter->ifp; struct ixgbe_hw *hw =3D &adapter->hw; + u32 ctrl, j; struct rx_ring *rxr; - u32 ctrl; =20 =20 /* @@ -4713,6 +4787,15 @@ ixgbe_setup_vlan_hw_support(struct adapter *adapte= if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) { ctrl &=3D ~IXGBE_VLNCTRL_CFIEN; ctrl |=3D IXGBE_VLNCTRL_VFE; + } else { + /* Zero vlan table */ + rxr =3D adapter->rx_rings; + + for (j =3D 0; j < adapter->num_queues; j++, rxr++) { + IXGBE_RX_LOCK(rxr); + memset(rxr->vlans->idx, 0, sizeof(struct ifvlans)); + IXGBE_RX_UNLOCK(rxr); + } } if (hw->mac.type =3D=3D ixgbe_mac_82598EB) ctrl |=3D IXGBE_VLNCTRL_VME; Index: sys/dev/ixgbe/ixgbe.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/dev/ixgbe/ixgbe.h (revision 248704) +++ sys/dev/ixgbe/ixgbe.h (working copy) @@ -284,6 +284,11 @@ struct ix_queue { u64 irqs; }; =20 +struct ifvlans { + struct ifnet *idx[4096]; +}; + + /* * The transmit ring, one per queue */ @@ -307,7 +312,6 @@ struct tx_ring { } queue_status; u32 txd_cmd; bus_dma_tag_t txtag; - char mtx_name[16]; #ifndef IXGBE_LEGACY_TX struct buf_ring *br; struct task txq_task; @@ -324,6 +328,7 @@ struct tx_ring { unsigned long no_tx_dma_setup; u64 no_desc_avail; u64 total_packets; + char mtx_name[16]; }; =20 =20 @@ -346,8 +351,8 @@ struct rx_ring { u16 num_desc; u16 mbuf_sz; u16 process_limit; - char mtx_name[16]; struct ixgbe_rx_buf *rx_buffers; + struct ifvlans *vlans; bus_dma_tag_t ptag; =20 u32 bytes; /* Used for AIM calc */ @@ -363,6 +368,7 @@ struct rx_ring { #ifdef IXGBE_FDIR u64 flm; #endif + char mtx_name[16]; }; =20 /* Our adapter structure */ --------------000509050108030808090809--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?516C3462.30501>