diff options
| author | Hans Petter Selasky <hselasky@FreeBSD.org> | 2017-01-18 13:31:17 +0000 |
|---|---|---|
| committer | Hans Petter Selasky <hselasky@FreeBSD.org> | 2017-01-18 13:31:17 +0000 |
| commit | f3e7afe2d7b262ab55ab818445d4dfdb6e0c70a9 (patch) | |
| tree | f99cc015b93fe941bf2c9800511d277156c375d9 /sys/net | |
| parent | ae69172343e8e6940510bf3cf7512fceaa479929 (diff) | |
Notes
Diffstat (limited to 'sys/net')
| -rw-r--r-- | sys/net/ieee8023ad_lacp.c | 31 | ||||
| -rw-r--r-- | sys/net/ieee8023ad_lacp.h | 3 | ||||
| -rw-r--r-- | sys/net/if.h | 1 | ||||
| -rw-r--r-- | sys/net/if_dead.c | 28 | ||||
| -rw-r--r-- | sys/net/if_lagg.c | 57 | ||||
| -rw-r--r-- | sys/net/if_var.h | 54 | ||||
| -rw-r--r-- | sys/net/if_vlan.c | 33 |
7 files changed, 205 insertions, 2 deletions
diff --git a/sys/net/ieee8023ad_lacp.c b/sys/net/ieee8023ad_lacp.c index 4863ac98035b..bf73a5c75e2b 100644 --- a/sys/net/ieee8023ad_lacp.c +++ b/sys/net/ieee8023ad_lacp.c @@ -30,6 +30,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_ratelimit.h" + #include <sys/param.h> #include <sys/callout.h> #include <sys/eventhandler.h> @@ -853,6 +855,35 @@ lacp_select_tx_port(struct lagg_softc *sc, struct mbuf *m) return (lp->lp_lagg); } + +#ifdef RATELIMIT +struct lagg_port * +lacp_select_tx_port_by_hash(struct lagg_softc *sc, uint32_t flowid) +{ + struct lacp_softc *lsc = LACP_SOFTC(sc); + struct lacp_portmap *pm; + struct lacp_port *lp; + uint32_t hash; + + if (__predict_false(lsc->lsc_suppress_distributing)) { + LACP_DPRINTF((NULL, "%s: waiting transit\n", __func__)); + return (NULL); + } + + pm = &lsc->lsc_pmap[lsc->lsc_activemap]; + if (pm->pm_count == 0) { + LACP_DPRINTF((NULL, "%s: no active aggregator\n", __func__)); + return (NULL); + } + + hash = flowid >> sc->flowid_shift; + hash %= pm->pm_count; + lp = pm->pm_map[hash]; + + return (lp->lp_lagg); +} +#endif + /* * lacp_suppress_distributing: drop transmit packets for a while * to preserve packet ordering. diff --git a/sys/net/ieee8023ad_lacp.h b/sys/net/ieee8023ad_lacp.h index 8f0f51a71c48..b26e2c9251f2 100644 --- a/sys/net/ieee8023ad_lacp.h +++ b/sys/net/ieee8023ad_lacp.h @@ -284,6 +284,9 @@ struct lacp_softc { struct mbuf *lacp_input(struct lagg_port *, struct mbuf *); struct lagg_port *lacp_select_tx_port(struct lagg_softc *, struct mbuf *); +#ifdef RATELIMIT +struct lagg_port *lacp_select_tx_port_by_hash(struct lagg_softc *, uint32_t); +#endif void lacp_attach(struct lagg_softc *); void lacp_detach(void *); void lacp_init(struct lagg_softc *); diff --git a/sys/net/if.h b/sys/net/if.h index 98ae0a823cd3..26f078700100 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -239,6 +239,7 @@ struct if_data { #define IFCAP_RXCSUM_IPV6 0x200000 /* can offload checksum on IPv6 RX */ #define IFCAP_TXCSUM_IPV6 0x400000 /* can offload checksum on IPv6 TX */ #define IFCAP_HWSTATS 0x800000 /* manages counters internally */ +#define IFCAP_TXRTLMT 0x1000000 /* hardware supports TX rate limiting */ #define IFCAP_HWCSUM_IPV6 (IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6) diff --git a/sys/net/if_dead.c b/sys/net/if_dead.c index 8b36ab348628..0e32dcf29116 100644 --- a/sys/net/if_dead.c +++ b/sys/net/if_dead.c @@ -100,6 +100,30 @@ ifdead_get_counter(struct ifnet *ifp, ift_counter cnt) return (0); } +static int +ifdead_snd_tag_alloc(struct ifnet *ifp, union if_snd_tag_alloc_params *params, + struct m_snd_tag **ppmt) +{ + return (EOPNOTSUPP); +} + +static int +ifdead_snd_tag_modify(struct m_snd_tag *pmt, union if_snd_tag_modify_params *params) +{ + return (EOPNOTSUPP); +} + +static int +ifdead_snd_tag_query(struct m_snd_tag *pmt, union if_snd_tag_query_params *params) +{ + return (EOPNOTSUPP); +} + +static void +ifdead_snd_tag_free(struct m_snd_tag *pmt) +{ +} + void if_dead(struct ifnet *ifp) { @@ -112,4 +136,8 @@ if_dead(struct ifnet *ifp) ifp->if_qflush = ifdead_qflush; ifp->if_transmit = ifdead_transmit; ifp->if_get_counter = ifdead_get_counter; + ifp->if_snd_tag_alloc = ifdead_snd_tag_alloc; + ifp->if_snd_tag_modify = ifdead_snd_tag_modify; + ifp->if_snd_tag_query = ifdead_snd_tag_query; + ifp->if_snd_tag_free = ifdead_snd_tag_free; } diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 0a5fc159e57b..b44fdc6e6c9c 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -23,6 +23,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_ratelimit.h" #include <sys/param.h> #include <sys/kernel.h> @@ -118,6 +119,11 @@ static void lagg_port2req(struct lagg_port *, struct lagg_reqport *); static void lagg_init(void *); static void lagg_stop(struct lagg_softc *); static int lagg_ioctl(struct ifnet *, u_long, caddr_t); +#ifdef RATELIMIT +static int lagg_snd_tag_alloc(struct ifnet *, + union if_snd_tag_alloc_params *, + struct m_snd_tag **); +#endif static int lagg_ether_setmulti(struct lagg_softc *); static int lagg_ether_cmdmulti(struct lagg_port *, int); static int lagg_setflag(struct lagg_port *, int, int, @@ -503,7 +509,12 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params) ifp->if_ioctl = lagg_ioctl; ifp->if_get_counter = lagg_get_counter; ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; +#ifdef RATELIMIT + ifp->if_snd_tag_alloc = lagg_snd_tag_alloc; + ifp->if_capenable = ifp->if_capabilities = IFCAP_HWSTATS | IFCAP_TXRTLMT; +#else ifp->if_capenable = ifp->if_capabilities = IFCAP_HWSTATS; +#endif /* * Attach as an ordinary ethernet device, children will be attached @@ -1549,6 +1560,52 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) return (error); } +#ifdef RATELIMIT +static int +lagg_snd_tag_alloc(struct ifnet *ifp, + union if_snd_tag_alloc_params *params, + struct m_snd_tag **ppmt) +{ + struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; + struct lagg_port *lp; + struct lagg_lb *lb; + uint32_t p; + + switch (sc->sc_proto) { + case LAGG_PROTO_FAILOVER: + lp = lagg_link_active(sc, sc->sc_primary); + break; + case LAGG_PROTO_LOADBALANCE: + if ((sc->sc_opts & LAGG_OPT_USE_FLOWID) == 0 || + params->hdr.flowtype == M_HASHTYPE_NONE) + return (EOPNOTSUPP); + p = params->hdr.flowid >> sc->flowid_shift; + p %= sc->sc_count; + lb = (struct lagg_lb *)sc->sc_psc; + lp = lb->lb_ports[p]; + lp = lagg_link_active(sc, lp); + break; + case LAGG_PROTO_LACP: + if ((sc->sc_opts & LAGG_OPT_USE_FLOWID) == 0 || + params->hdr.flowtype == M_HASHTYPE_NONE) + return (EOPNOTSUPP); + lp = lacp_select_tx_port_by_hash(sc, params->hdr.flowid); + break; + default: + return (EOPNOTSUPP); + } + if (lp == NULL) + return (EOPNOTSUPP); + ifp = lp->lp_ifp; + if (ifp == NULL || ifp->if_snd_tag_alloc == NULL || + (ifp->if_capenable & IFCAP_TXRTLMT) == 0) + return (EOPNOTSUPP); + + /* forward allocation request */ + return (ifp->if_snd_tag_alloc(ifp, params, ppmt)); +} +#endif + static int lagg_ether_setmulti(struct lagg_softc *sc) { diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 62c4bfdd33fb..7c8fd7ec80a4 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -175,6 +175,49 @@ struct if_encap_req { #define IFENCAP_FLAG_BROADCAST 0x02 /* Destination is broadcast */ +/* + * Network interface send tag support. The storage of "struct + * m_snd_tag" comes from the network driver and it is free to allocate + * as much additional space as it wants for its own use. + */ +struct m_snd_tag; + +#define IF_SND_TAG_TYPE_RATE_LIMIT 0 +#define IF_SND_TAG_TYPE_MAX 1 + +struct if_snd_tag_alloc_header { + uint32_t type; /* send tag type, see IF_SND_TAG_XXX */ + uint32_t flowid; /* mbuf hash value */ + uint32_t flowtype; /* mbuf hash type */ +}; + +struct if_snd_tag_alloc_rate_limit { + struct if_snd_tag_alloc_header hdr; + uint64_t max_rate; /* in bytes/s */ +}; + +struct if_snd_tag_rate_limit_params { + uint64_t max_rate; /* in bytes/s */ +}; + +union if_snd_tag_alloc_params { + struct if_snd_tag_alloc_header hdr; + struct if_snd_tag_alloc_rate_limit rate_limit; +}; + +union if_snd_tag_modify_params { + struct if_snd_tag_rate_limit_params rate_limit; +}; + +union if_snd_tag_query_params { + struct if_snd_tag_rate_limit_params rate_limit; +}; + +typedef int (if_snd_tag_alloc_t)(struct ifnet *, union if_snd_tag_alloc_params *, + struct m_snd_tag **); +typedef int (if_snd_tag_modify_t)(struct m_snd_tag *, union if_snd_tag_modify_params *); +typedef int (if_snd_tag_query_t)(struct m_snd_tag *, union if_snd_tag_query_params *); +typedef void (if_snd_tag_free_t)(struct m_snd_tag *); /* * Structure defining a network interface. @@ -304,12 +347,19 @@ struct ifnet { u_int if_hw_tsomaxsegsize; /* TSO maximum segment size in bytes */ /* + * Network adapter send tag support: + */ + if_snd_tag_alloc_t *if_snd_tag_alloc; + if_snd_tag_modify_t *if_snd_tag_modify; + if_snd_tag_query_t *if_snd_tag_query; + if_snd_tag_free_t *if_snd_tag_free; + + /* * Spare fields to be added before branching a stable branch, so * that structure can be enhanced without changing the kernel * binary interface. */ - void *if_pspare[4]; /* packet pacing / general use */ - int if_ispare[4]; /* packet pacing / general use */ + int if_ispare[4]; /* general use */ }; /* for compatibility with other BSDs */ diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 73470dc80e3f..608826a6dc92 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_vlan.h" +#include "opt_ratelimit.h" #include <sys/param.h> #include <sys/eventhandler.h> @@ -212,6 +213,10 @@ static void trunk_destroy(struct ifvlantrunk *trunk); static void vlan_init(void *foo); static void vlan_input(struct ifnet *ifp, struct mbuf *m); static int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr); +#ifdef RATELIMIT +static int vlan_snd_tag_alloc(struct ifnet *, + union if_snd_tag_alloc_params *, struct m_snd_tag **); +#endif static void vlan_qflush(struct ifnet *ifp); static int vlan_setflag(struct ifnet *ifp, int flag, int status, int (*func)(struct ifnet *, int)); @@ -971,6 +976,9 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) ifp->if_transmit = vlan_transmit; ifp->if_qflush = vlan_qflush; ifp->if_ioctl = vlan_ioctl; +#ifdef RATELIMIT + ifp->if_snd_tag_alloc = vlan_snd_tag_alloc; +#endif ifp->if_flags = VLAN_IFFLAGS; ether_ifattach(ifp, eaddr); /* Now undo some of the damage... */ @@ -1591,6 +1599,15 @@ vlan_capabilities(struct ifvlan *ifv) TOEDEV(ifp) = TOEDEV(p); ifp->if_capenable |= p->if_capenable & IFCAP_TOE; } + +#ifdef RATELIMIT + /* + * If the parent interface supports ratelimiting, so does the + * VLAN interface. + */ + ifp->if_capabilities |= (p->if_capabilities & IFCAP_TXRTLMT); + ifp->if_capenable |= (p->if_capenable & IFCAP_TXRTLMT); +#endif } static void @@ -1801,3 +1818,19 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) return (error); } + +#ifdef RATELIMIT +static int +vlan_snd_tag_alloc(struct ifnet *ifp, + union if_snd_tag_alloc_params *params, + struct m_snd_tag **ppmt) +{ + + /* get trunk device */ + ifp = vlan_trunkdev(ifp); + if (ifp == NULL || (ifp->if_capenable & IFCAP_TXRTLMT) == 0) + return (EOPNOTSUPP); + /* forward allocation request */ + return (ifp->if_snd_tag_alloc(ifp, params, ppmt)); +} +#endif |
