1 /* $NetBSD: if_laggproto.h,v 1.5 2021/09/30 04:23:30 yamaguchi Exp $ */ 2 3 /* 4 * Copyright (c) 2021 Internet Initiative Japan Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef _NET_LAGG_IF_LAGGPROTO_H_ 30 #define _NET_LAGG_IF_LAGGPROTO_H_ 31 32 struct lagg_softc; 33 struct lagg_proto_softc; 34 35 #define LAGG_MAX_PORTS 32 36 #define LAGG_PORT_PRIO 0x8000U 37 38 enum lagg_work_state { 39 LAGG_WORK_IDLE, 40 LAGG_WORK_ENQUEUED, 41 LAGG_WORK_STOPPING 42 }; 43 struct lagg_work { 44 struct work lw_cookie; 45 void (*lw_func)(struct lagg_work *, void *); 46 void *lw_arg; 47 int lw_state; 48 }; 49 50 static inline void 51 lagg_work_set(struct lagg_work *w, 52 void (*func)(struct lagg_work *, void *), void *arg) 53 { 54 55 w->lw_func = func; 56 w->lw_arg = arg; 57 } 58 59 struct workqueue * 60 lagg_workq_create(const char *, pri_t, int, int); 61 void lagg_workq_destroy(struct workqueue *); 62 void lagg_workq_add(struct workqueue *, struct lagg_work *); 63 void lagg_workq_wait(struct workqueue *, struct lagg_work *); 64 65 struct lagg_port { 66 struct psref_target lp_psref; 67 struct ifnet *lp_ifp; /* physical interface */ 68 struct lagg_softc *lp_softc; /* parent lagg */ 69 void *lp_proto_ctx; 70 bool lp_detaching; 71 void *lp_linkstate_hook; 72 73 uint32_t lp_prio; /* port priority */ 74 uint32_t lp_flags; /* port flags */ 75 76 u_char lp_iftype; 77 uint8_t lp_lladdr[ETHER_ADDR_LEN]; 78 int (*lp_ioctl)(struct ifnet *, u_long, void *); 79 int (*lp_output)(struct ifnet *, struct mbuf *, 80 const struct sockaddr *, 81 const struct rtentry *); 82 uint64_t lp_ifcapenable; 83 uint64_t lp_mtu; 84 85 SIMPLEQ_ENTRY(lagg_port) 86 lp_entry; 87 }; 88 89 struct lagg_proto { 90 lagg_proto pr_num; 91 void (*pr_init)(void); 92 void (*pr_fini)(void); 93 int (*pr_attach)(struct lagg_softc *, 94 struct lagg_proto_softc **); 95 void (*pr_detach)(struct lagg_proto_softc *); 96 int (*pr_up)(struct lagg_proto_softc *); 97 void (*pr_down)(struct lagg_proto_softc *); 98 int (*pr_transmit)(struct lagg_proto_softc *, 99 struct mbuf *); 100 struct mbuf * (*pr_input)(struct lagg_proto_softc *, 101 struct lagg_port *, struct mbuf *); 102 int (*pr_allocport)(struct lagg_proto_softc *, 103 struct lagg_port *); 104 void (*pr_freeport)(struct lagg_proto_softc *, 105 struct lagg_port *); 106 void (*pr_startport)(struct lagg_proto_softc *, 107 struct lagg_port *); 108 void (*pr_stopport)(struct lagg_proto_softc *, 109 struct lagg_port *); 110 void (*pr_protostat)(struct lagg_proto_softc *, 111 struct laggreqproto *); 112 void (*pr_portstat)(struct lagg_proto_softc *, 113 struct lagg_port *, struct laggreqport *); 114 void (*pr_linkstate)(struct lagg_proto_softc *, 115 struct lagg_port *); 116 int (*pr_ioctl)(struct lagg_proto_softc *, 117 struct laggreqproto *); 118 }; 119 120 struct lagg_variant { 121 lagg_proto lv_proto; 122 struct lagg_proto_softc 123 *lv_psc; 124 125 struct psref_target lv_psref; 126 }; 127 128 struct lagg_mc_entry { 129 LIST_ENTRY(lagg_mc_entry) 130 mc_entry; 131 struct ether_multi *mc_enm; 132 struct sockaddr_storage mc_addr; 133 }; 134 135 struct lagg_vlantag { 136 uint16_t lvt_vtag; 137 TAILQ_ENTRY(lagg_vlantag) 138 lvt_entry; 139 }; 140 141 struct lagg_softc { 142 kmutex_t sc_lock; 143 struct ifmedia sc_media; 144 u_char sc_iftype; 145 146 /* interface link-layer address */ 147 uint8_t sc_lladdr[ETHER_ADDR_LEN]; 148 /* generated random lladdr */ 149 uint8_t sc_lladdr_rand[ETHER_ADDR_LEN]; 150 151 LIST_HEAD(, lagg_mc_entry) 152 sc_mclist; 153 TAILQ_HEAD(, lagg_vlantag) 154 sc_vtags; 155 pserialize_t sc_psz; 156 struct lagg_variant *sc_var; 157 SIMPLEQ_HEAD(, lagg_port) 158 sc_ports; 159 size_t sc_nports; 160 char sc_evgroup[16]; 161 struct evcnt sc_novar; 162 163 struct sysctllog *sc_sysctllog; 164 const struct sysctlnode *sc_sysctlnode; 165 bool sc_hash_mac; 166 bool sc_hash_ipaddr; 167 bool sc_hash_ip6addr; 168 bool sc_hash_tcp; 169 bool sc_hash_udp; 170 171 /* 172 * storage size of sc_if is a variable-length, 173 * should be the last 174 */ 175 struct ifnet sc_if; 176 }; 177 178 /* 179 * Locking notes: 180 * - sc_lock(LAGG_LOCK()) is an adaptive mutex and protects items 181 * of struct lagg_softc 182 * - a lock in struct lagg_proto_softc, for example LACP_LOCK(), is 183 * an adaptive mutex and protects member contained in the struct 184 * - sc_var is protected by both pselialize (sc_psz) and psref (lv_psref) 185 * - Updates of sc_var is serialized by sc_lock 186 * - Items in sc_ports is protected by both psref (lp_psref) and 187 * pserialize contained in struct lagg_proto_softc 188 * - details are discribed in if_laggport.c and if_lagg_lacp.c 189 * - Updates of items in sc_ports are serialized by sc_lock 190 * - an instance referenced by lp_proto_ctx in struct lagg_port is 191 * protected by a lock in struct lagg_proto_softc 192 * 193 * Locking order: 194 * - IFNET_LOCK(sc_if) -> LAGG_LOCK -> ETHER_LOCK(sc_if) -> a lock in 195 * struct lagg_port_softc 196 * - IFNET_LOCK(sc_if) -> LAGG_LOCK -> IFNET_LOCK(lp_ifp) 197 * - Currently, there is no combination of following locks 198 * - IFNET_LOCK(lp_ifp) and a lock in struct lagg_proto_softc 199 * - IFNET_LOCK(lp_ifp) and ETHER_LOCK(sc_if) 200 */ 201 #define LAGG_LOCK(_sc) mutex_enter(&(_sc)->sc_lock) 202 #define LAGG_UNLOCK(_sc) mutex_exit(&(_sc)->sc_lock) 203 #define LAGG_LOCKED(_sc) mutex_owned(&(_sc)->sc_lock) 204 #define LAGG_CLLADDR(_sc) CLLADDR((_sc)->sc_if.if_sadl) 205 206 #define LAGG_PORTS_FOREACH(_sc, _lp) \ 207 SIMPLEQ_FOREACH((_lp), &(_sc)->sc_ports, lp_entry) 208 #define LAGG_PORTS_FOREACH_SAFE(_sc, _lp, _lptmp) \ 209 SIMPLEQ_FOREACH_SAFE((_lp), &(_sc)->sc_ports, lp_entry, (_lptmp)) 210 #define LAGG_PORTS_EMPTY(_sc) SIMPLEQ_EMPTY(&(_sc)->sc_ports) 211 #define LAGG_PORT_IOCTL(_lp, _cmd, _data) \ 212 (_lp)->lp_ioctl == NULL ? ENOTTY : \ 213 (_lp)->lp_ioctl((_lp)->lp_ifp, (_cmd), (_data)) 214 215 216 static inline const void * 217 lagg_m_extract(struct mbuf *m, size_t off, size_t reqlen, void *buf) 218 { 219 ssize_t len; 220 const void *rv; 221 222 KASSERT(ISSET(m->m_flags, M_PKTHDR)); 223 len = off + reqlen; 224 225 if (m->m_pkthdr.len < len) { 226 return NULL; 227 } 228 229 if (m->m_len >= len) { 230 rv = mtod(m, uint8_t *) + off; 231 } else { 232 m_copydata(m, off, reqlen, buf); 233 rv = buf; 234 } 235 236 return rv; 237 } 238 239 static inline int 240 lagg_port_xmit(struct lagg_port *lp, struct mbuf *m) 241 { 242 243 return if_transmit_lock(lp->lp_ifp, m); 244 } 245 246 static inline bool 247 lagg_portactive(struct lagg_port *lp) 248 { 249 struct ifnet *ifp; 250 251 ifp = lp->lp_ifp; 252 253 if (ifp->if_link_state != LINK_STATE_DOWN && 254 ISSET(ifp->if_flags, IFF_UP)) { 255 return true; 256 } 257 258 return false; 259 } 260 261 void lagg_log(struct lagg_softc *, int, const char *, ...) 262 __printflike(3, 4); 263 void lagg_port_getref(struct lagg_port *, struct psref *); 264 void lagg_port_putref(struct lagg_port *, struct psref *); 265 void lagg_enqueue(struct lagg_softc *, 266 struct lagg_port *, struct mbuf *); 267 uint32_t lagg_hashmbuf(struct lagg_softc *, struct mbuf *); 268 269 void lagg_common_detach(struct lagg_proto_softc *); 270 int lagg_common_allocport(struct lagg_proto_softc *, 271 struct lagg_port *); 272 void lagg_common_freeport(struct lagg_proto_softc *, 273 struct lagg_port *); 274 void lagg_common_startport(struct lagg_proto_softc *, 275 struct lagg_port *); 276 void lagg_common_stopport(struct lagg_proto_softc *, 277 struct lagg_port *); 278 void lagg_common_linkstate(struct lagg_proto_softc *, 279 struct lagg_port *); 280 281 int lagg_none_attach(struct lagg_softc *, 282 struct lagg_proto_softc **); 283 int lagg_none_up(struct lagg_proto_softc *); 284 285 int lagg_fail_attach(struct lagg_softc *, 286 struct lagg_proto_softc **); 287 int lagg_fail_transmit(struct lagg_proto_softc *, struct mbuf *); 288 struct mbuf * lagg_fail_input(struct lagg_proto_softc *, struct lagg_port *, 289 struct mbuf *); 290 void lagg_fail_portstat(struct lagg_proto_softc *, 291 struct lagg_port *, struct laggreqport *); 292 int lagg_fail_ioctl(struct lagg_proto_softc *, 293 struct laggreqproto *); 294 295 int lagg_lb_attach(struct lagg_softc *, struct lagg_proto_softc **); 296 void lagg_lb_startport(struct lagg_proto_softc *, 297 struct lagg_port *); 298 void lagg_lb_stopport(struct lagg_proto_softc *, struct lagg_port *); 299 int lagg_lb_transmit(struct lagg_proto_softc *, struct mbuf *); 300 struct mbuf * lagg_lb_input(struct lagg_proto_softc *, struct lagg_port *, 301 struct mbuf *); 302 void lagg_lb_portstat(struct lagg_proto_softc *, 303 struct lagg_port *, struct laggreqport *); 304 305 int lacp_attach(struct lagg_softc *, struct lagg_proto_softc **); 306 void lacp_detach(struct lagg_proto_softc *); 307 int lacp_up(struct lagg_proto_softc *); 308 void lacp_down(struct lagg_proto_softc *); 309 int lacp_transmit(struct lagg_proto_softc *, struct mbuf *); 310 struct mbuf * lacp_input(struct lagg_proto_softc *, struct lagg_port *, 311 struct mbuf *); 312 int lacp_allocport(struct lagg_proto_softc *, struct lagg_port *); 313 void lacp_freeport(struct lagg_proto_softc *, struct lagg_port *); 314 void lacp_startport(struct lagg_proto_softc *, struct lagg_port *); 315 void lacp_stopport(struct lagg_proto_softc *, struct lagg_port *); 316 void lacp_protostat(struct lagg_proto_softc *, 317 struct laggreqproto *); 318 void lacp_portstat(struct lagg_proto_softc *, struct lagg_port *, 319 struct laggreqport *); 320 void lacp_linkstate(struct lagg_proto_softc *, struct lagg_port *); 321 int lacp_ioctl(struct lagg_proto_softc *, struct laggreqproto *); 322 #endif 323