xref: /xnu-8796.101.5/bsd/skywalk/nexus/netif/nx_netif_vp.c (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
1 /*
2  * Copyright (c) 2019-2022 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <skywalk/os_skywalk_private.h>
30 #include <skywalk/nexus/netif/nx_netif.h>
31 #include <net/if_vlan_var.h>
32 #include <sys/sdt.h>
33 
34 #define NETIF_DEMUX_ALLOC_SLOTS 128
35 
36 #define OUTBOUND_CHECK_OFF      0
37 #define OUTBOUND_CHECK_ON       1
38 #define OUTBOUND_CHECK_FORCED   2
39 
40 /* Turning this off allows packets to be spoofed for testing purposes */
41 static uint32_t outbound_check = OUTBOUND_CHECK_ON;
42 
43 /* This controls the per-NA pool size of custom ether and llw NAs */
44 static uint32_t vp_pool_size = 2048;
45 
46 /* This enables zerocopy on llw NAs */
47 static uint32_t vp_zerocopy = 0;
48 
49 /* TX Ring size */
50 static uint32_t vp_tx_slots = 0;
51 
52 /* RX Ring size */
53 static uint32_t vp_rx_slots = 0;
54 
55 /*
56  * Disable all packet validation
57  */
58 uint32_t nx_netif_vp_accept_all = 0;
59 
60 static uint16_t nx_netif_vpna_gencnt = 0;
61 
62 #if (DEVELOPMENT || DEBUG)
63 SYSCTL_UINT(_kern_skywalk_netif, OID_AUTO, outbound_check,
64     CTLFLAG_RW | CTLFLAG_LOCKED, &outbound_check, 0,
65     "netif outbound packet validation");
66 SYSCTL_UINT(_kern_skywalk_netif, OID_AUTO, vp_pool_size,
67     CTLFLAG_RW | CTLFLAG_LOCKED, &vp_pool_size, 0,
68     "netif virtual port pool size");
69 SYSCTL_UINT(_kern_skywalk_netif, OID_AUTO, vp_zerocopy,
70     CTLFLAG_RW | CTLFLAG_LOCKED, &vp_zerocopy, 0,
71     "netif virtual port zero copy");
72 SYSCTL_UINT(_kern_skywalk_netif, OID_AUTO, vp_tx_slots,
73     CTLFLAG_RW | CTLFLAG_LOCKED, &vp_tx_slots, 0,
74     "netif virtual port tx slots");
75 SYSCTL_UINT(_kern_skywalk_netif, OID_AUTO, vp_rx_slots,
76     CTLFLAG_RW | CTLFLAG_LOCKED, &vp_rx_slots, 0,
77     "netif virtual port rx slots");
78 SYSCTL_UINT(_kern_skywalk_netif, OID_AUTO, vp_accept_all,
79     CTLFLAG_RW | CTLFLAG_LOCKED, &nx_netif_vp_accept_all, 0,
80     "netif accept all");
81 #endif /* (DEVELOPMENT || DEBUG) */
82 
83 static int
84 netif_vp_na_channel_event_notify(struct nexus_adapter *,
85     struct __kern_channel_event *, uint16_t);
86 
87 static void
netif_vp_dump_packet(struct __kern_packet * pkt)88 netif_vp_dump_packet(struct __kern_packet *pkt)
89 {
90 	uint8_t *baddr;
91 
92 	MD_BUFLET_ADDR_ABS(pkt, baddr);
93 	ASSERT(baddr != NULL);
94 	baddr += pkt->pkt_headroom;
95 
96 	DTRACE_SKYWALK2(dump__packet, struct __kern_packet *,
97 	    pkt, uint8_t *, baddr);
98 }
99 
100 static int
netif_copy_or_attach_pkt(struct __kern_channel_ring * ring,kern_channel_slot_t slot,struct __kern_packet * pkt)101 netif_copy_or_attach_pkt(struct __kern_channel_ring *ring,
102     kern_channel_slot_t slot, struct __kern_packet *pkt)
103 {
104 	kern_packet_t ph;
105 	struct __kern_packet *dpkt;
106 	errno_t err;
107 
108 	if (pkt->pkt_qum.qum_pp == ring->ckr_pp) {
109 		DTRACE_SKYWALK2(attach__pkt, struct __kern_channel_ring *, ring,
110 		    struct __kern_packet *, pkt);
111 		ph = SK_PKT2PH(pkt);
112 		err = kern_packet_finalize(ph);
113 		VERIFY(err == 0);
114 	} else {
115 		DTRACE_SKYWALK2(copy__pkt, struct __kern_channel_ring *, ring,
116 		    struct __kern_packet *, pkt);
117 		dpkt = nx_netif_pkt_to_pkt(NIFNA(ring->ckr_na), pkt,
118 		    ring->ckr_na->na_type == NA_NETIF_VP ? NETIF_CONVERT_RX :
119 		    NETIF_CONVERT_TX);
120 		if (__improbable(dpkt == NULL)) {
121 			return ENOMEM;
122 		}
123 		ph = SK_PKT2PH(dpkt);
124 	}
125 	err = kern_channel_slot_attach_packet(ring, slot, ph);
126 	VERIFY(err == 0);
127 	return 0;
128 }
129 
130 static errno_t
netif_deliver_pkt(struct nexus_adapter * na,struct __kern_packet * pkt_chain,uint32_t flags)131 netif_deliver_pkt(struct nexus_adapter *na, struct __kern_packet *pkt_chain,
132     uint32_t flags)
133 {
134 #pragma unused(flags)
135 	struct __kern_channel_ring *ring = &na->na_rx_rings[0];
136 	struct __kern_packet *pkt = pkt_chain, *next;
137 	kern_channel_slot_t last_slot = NULL, slot = NULL;
138 	struct nexus_netif_adapter *nifna = NIFNA(na);
139 	struct nx_netif *nif = nifna->nifna_netif;
140 	struct netif_stats *nifs = &nif->nif_stats;
141 	sk_protect_t protect;
142 	int cnt = 0, dropcnt = 0, err;
143 
144 	(void) kr_enter(ring, TRUE);
145 	protect = sk_sync_protect();
146 
147 	if (__improbable(KR_DROP(ring))) {
148 		nx_netif_free_packet_chain(pkt, &dropcnt);
149 		STATS_ADD(nifs,
150 		    NETIF_STATS_VP_DROP_USER_RING_DISABLED, dropcnt);
151 		STATS_ADD(nifs, NETIF_STATS_DROP, dropcnt);
152 		DTRACE_SKYWALK2(ring__drop, struct __kern_channel_ring *, ring,
153 		    int, dropcnt);
154 		sk_sync_unprotect(protect);
155 		kr_exit(ring);
156 		return ENXIO;
157 	}
158 	while (pkt != NULL) {
159 		slot = kern_channel_get_next_slot(ring, last_slot, NULL);
160 		if (slot == NULL) {
161 			break;
162 		}
163 		next = pkt->pkt_nextpkt;
164 		pkt->pkt_nextpkt = NULL;
165 		netif_vp_dump_packet(pkt);
166 		err = netif_copy_or_attach_pkt(ring, slot, pkt);
167 		if (__probable(err == 0)) {
168 			last_slot = slot;
169 		}
170 		pkt = next;
171 		cnt++;
172 	}
173 	if (NETIF_IS_LOW_LATENCY(nif)) {
174 		STATS_ADD(nifs, NETIF_STATS_VP_LL_DELIVERED, cnt);
175 	} else {
176 		STATS_ADD(nifs, NETIF_STATS_VP_DELIVERED, cnt);
177 	}
178 	DTRACE_SKYWALK4(delivered, struct nexus_adapter *, na,
179 	    struct __kern_channel_ring *, ring, struct __kern_packet *, pkt,
180 	    int, cnt);
181 
182 	if (pkt != NULL) {
183 		nx_netif_free_packet_chain(pkt, &dropcnt);
184 		STATS_ADD(nifs,
185 		    NETIF_STATS_VP_DROP_USER_RING_NO_SPACE, dropcnt);
186 		STATS_ADD(nifs, NETIF_STATS_DROP, dropcnt);
187 		DTRACE_SKYWALK2(deliver__drop, struct nexus_adapter *, na,
188 		    int, dropcnt);
189 	}
190 	if (last_slot != NULL) {
191 		kern_channel_advance_slot(ring, last_slot);
192 	}
193 	sk_sync_unprotect(protect);
194 	kr_exit(ring);
195 	if (cnt > 0) {
196 		(void) kern_channel_notify(ring, 0);
197 	}
198 	return 0;
199 }
200 
201 static errno_t
netif_deliver_cb(void * arg,void * chain,uint32_t flags)202 netif_deliver_cb(void *arg, void *chain, uint32_t flags)
203 {
204 	return netif_deliver_pkt(arg, chain, flags);
205 }
206 
207 static int
netif_hwna_rx_get_pkts(struct __kern_channel_ring * ring,struct proc * p,uint32_t flags,struct __kern_packet ** chain)208 netif_hwna_rx_get_pkts(struct __kern_channel_ring *ring, struct proc *p,
209     uint32_t flags, struct __kern_packet **chain)
210 {
211 	int err, cnt = 0;
212 	sk_protect_t protect;
213 	slot_idx_t ktail, idx;
214 	struct __kern_packet *pkt_chain = NULL, **tailp = &pkt_chain;
215 	struct netif_stats *nifs = &NIFNA(KRNA(ring))->nifna_netif->nif_stats;
216 
217 	err = kr_enter(ring, ((flags & NA_NOTEF_CAN_SLEEP) != 0 ||
218 	    (ring->ckr_flags & CKRF_HOST) != 0));
219 	if (err != 0) {
220 		SK_DF(SK_VERB_VP,
221 		    "hwna \"%s\" (0x%llx) kr \"%s\" (0x%llx) krflags 0x%b "
222 		    "(%d)", KRNA(ring)->na_name, SK_KVA(KRNA(ring)),
223 		    ring->ckr_name, SK_KVA(ring), ring->ckr_flags,
224 		    CKRF_BITS, err);
225 		STATS_INC(nifs, NETIF_STATS_VP_KR_ENTER_FAIL);
226 		return err;
227 	}
228 	if (__improbable(KR_DROP(ring))) {
229 		kr_exit(ring);
230 		STATS_INC(nifs, NETIF_STATS_VP_DEV_RING_DISABLED);
231 		return ENODEV;
232 	}
233 	protect = sk_sync_protect();
234 
235 	err = ring->ckr_na_sync(ring, p, 0);
236 	if (err != 0 && err != EAGAIN) {
237 		STATS_INC(nifs, NETIF_STATS_VP_SYNC_UNKNOWN_ERR);
238 		goto out;
239 	}
240 	ktail = ring->ckr_ktail;
241 	if (__improbable(ring->ckr_khead == ktail)) {
242 		SK_DF(SK_VERB_VP,
243 		    "spurious wakeup on hwna %s (0x%llx)", KRNA(ring)->na_name,
244 		    SK_KVA(KRNA(ring)));
245 		STATS_INC(nifs, NETIF_STATS_VP_SPURIOUS_NOTIFY);
246 		err = ENOENT;
247 		goto out;
248 	}
249 	/* get all packets from the ring */
250 	idx = ring->ckr_rhead;
251 	while (idx != ktail) {
252 		struct __kern_slot_desc *ksd = KR_KSD(ring, idx);
253 		struct __kern_packet *pkt = ksd->sd_pkt;
254 
255 		ASSERT(pkt->pkt_nextpkt == NULL);
256 		KR_SLOT_DETACH_METADATA(ring, ksd);
257 		cnt++;
258 		*tailp = pkt;
259 		tailp = &pkt->pkt_nextpkt;
260 		idx = SLOT_NEXT(idx, ring->ckr_lim);
261 	}
262 	ring->ckr_rhead = ktail;
263 	ring->ckr_rtail = ring->ckr_ktail;
264 
265 	DTRACE_SKYWALK2(rx__notify, struct __kern_channel_ring *, ring,
266 	    int, cnt);
267 	*chain = pkt_chain;
268 out:
269 	sk_sync_unprotect(protect);
270 	kr_exit(ring);
271 	return err;
272 }
273 
274 int
netif_llw_rx_notify_fast(struct __kern_channel_ring * ring,struct proc * p,uint32_t flags)275 netif_llw_rx_notify_fast(struct __kern_channel_ring *ring, struct proc *p,
276     uint32_t flags)
277 {
278 #pragma unused (p, flags)
279 	struct nexus_adapter *hwna;
280 	uint32_t count;
281 	int i, err;
282 
283 	hwna = KRNA(ring);
284 	count = na_get_nslots(hwna, NR_RX);
285 	err = nx_rx_sync_packets(ring, ring->ckr_scratch, &count);
286 	if (__improbable(err != 0)) {
287 		SK_ERR("nx_rx_sync_packets failed: %d", err);
288 		DTRACE_SKYWALK2(rx__sync__packets__failed,
289 		    struct __kern_channel_ring *, ring, int, err);
290 		return err;
291 	}
292 	DTRACE_SKYWALK1(chain__count, uint32_t, count);
293 	for (i = 0; i < count; i++) {
294 		struct __kern_packet *pkt_chain;
295 
296 		pkt_chain = SK_PTR_ADDR_KPKT(ring->ckr_scratch[i]);
297 		ASSERT(pkt_chain != NULL);
298 		(void) nx_netif_demux(NIFNA(KRNA(ring)), pkt_chain, NULL,
299 		    NETIF_FLOW_SOURCE);
300 	}
301 	return 0;
302 }
303 
304 int
netif_llw_rx_notify_default(struct __kern_channel_ring * ring,struct proc * p,uint32_t flags)305 netif_llw_rx_notify_default(struct __kern_channel_ring *ring, struct proc *p,
306     uint32_t flags)
307 {
308 	int err;
309 	struct __kern_packet *pkt_chain = NULL;
310 
311 	err = netif_hwna_rx_get_pkts(ring, p, flags, &pkt_chain);
312 	if (err != 0) {
313 		return err;
314 	}
315 	return nx_netif_demux(NIFNA(KRNA(ring)), pkt_chain, NULL,
316 	           NETIF_FLOW_SOURCE);
317 }
318 
319 static errno_t
netif_hwna_setup(struct nx_netif * nif)320 netif_hwna_setup(struct nx_netif *nif)
321 {
322 	struct kern_channel *ch;
323 	struct kern_nexus *nx = nif->nif_nx;
324 	struct chreq chr;
325 	int err;
326 
327 	SK_LOCK_ASSERT_HELD();
328 	ASSERT(NETIF_IS_LOW_LATENCY(nif));
329 	if (nif->nif_hw_ch != NULL) {
330 		nif->nif_hw_ch_refcnt++;
331 		SK_DF(SK_VERB_VP, "%s: hw channel already open, refcnt %d",
332 		    if_name(nif->nif_ifp), nif->nif_hw_ch_refcnt);
333 		return 0;
334 	}
335 	ASSERT(nif->nif_hw_ch_refcnt == 0);
336 	bzero(&chr, sizeof(chr));
337 	uuid_copy(chr.cr_spec_uuid, nx->nx_uuid);
338 	chr.cr_ring_id = 0;
339 	chr.cr_port = NEXUS_PORT_NET_IF_DEV;
340 	chr.cr_mode |= CHMODE_CONFIG;
341 
342 	err = 0;
343 	ch = ch_open_special(nx, &chr, FALSE, &err);
344 	if (ch == NULL) {
345 		SK_ERR("%s: failed to open nx 0x%llx (err %d)",
346 		    if_name(nif->nif_ifp), SK_KVA(nx), err);
347 		return err;
348 	}
349 	netif_hwna_set_mode(ch->ch_na, NETIF_MODE_LLW, NULL);
350 	na_start_spec(nx, ch);
351 	nif->nif_hw_ch_refcnt = 1;
352 	nif->nif_hw_ch = ch;
353 	SK_DF(SK_VERB_VP, "%s: hw channel opened 0x%llx, %s:%s",
354 	    if_name(nif->nif_ifp), SK_KVA(ch), NX_DOM(nx)->nxdom_name,
355 	    NX_DOM_PROV(nx)->nxdom_prov_name);
356 	return 0;
357 }
358 
359 static void
netif_hwna_teardown(struct nx_netif * nif)360 netif_hwna_teardown(struct nx_netif *nif)
361 {
362 	struct kern_nexus *nx = nif->nif_nx;
363 	struct kern_channel *ch = nif->nif_hw_ch;
364 
365 	SK_LOCK_ASSERT_HELD();
366 	ASSERT(NETIF_IS_LOW_LATENCY(nif));
367 	ASSERT(ch != NULL);
368 	if (--nif->nif_hw_ch_refcnt > 0) {
369 		SK_DF(SK_VERB_VP, "%s: hw channel still open, refcnt %d",
370 		    if_name(nif->nif_ifp), nif->nif_hw_ch_refcnt);
371 		return;
372 	}
373 	SK_DF(SK_VERB_VP, "%s: hw channel closing 0x%llx, %s:%s",
374 	    if_name(nif->nif_ifp), SK_KVA(ch), NX_DOM(nx)->nxdom_name,
375 	    NX_DOM_PROV(nx)->nxdom_prov_name);
376 
377 	na_stop_spec(nx, ch);
378 	netif_hwna_clear_mode(ch->ch_na);
379 	ch_close_special(ch);
380 	(void) ch_release_locked(ch);
381 	nif->nif_hw_ch = NULL;
382 	SK_DF(SK_VERB_VP, "%s: hw channel closed, %s:%s",
383 	    if_name(nif->nif_ifp), NX_DOM(nx)->nxdom_name,
384 	    NX_DOM_PROV(nx)->nxdom_prov_name);
385 }
386 
387 static int
netif_vp_na_activate_on(struct nexus_adapter * na)388 netif_vp_na_activate_on(struct nexus_adapter *na)
389 {
390 	errno_t err;
391 	struct netif_flow *nf;
392 	struct netif_port_info npi;
393 	struct nexus_netif_adapter *nifna;
394 	struct nx_netif *nif;
395 	boolean_t hwna_setup = FALSE;
396 
397 	nifna = NIFNA(na);
398 	nif = nifna->nifna_netif;
399 
400 	/* lock needed to protect against nxdom_unbind_port */
401 	NETIF_WLOCK(nif);
402 	err = nx_port_get_info(nif->nif_nx, na->na_nx_port,
403 	    NX_PORT_INFO_TYPE_NETIF, &npi, sizeof(npi));
404 	NETIF_WUNLOCK(nif);
405 	if (err != 0) {
406 		SK_ERR("port info not found: %d", err);
407 		return err;
408 	}
409 	if (NETIF_IS_LOW_LATENCY(nif)) {
410 		err = netif_hwna_setup(nif);
411 		if (err != 0) {
412 			return err;
413 		}
414 		hwna_setup = TRUE;
415 	}
416 	err = nx_netif_flow_add(nif, na->na_nx_port, &npi.npi_fd, na,
417 	    netif_deliver_cb, &nf);
418 	if (err != 0) {
419 		if (hwna_setup) {
420 			netif_hwna_teardown(nif);
421 		}
422 		return err;
423 	}
424 	nifna->nifna_flow = nf;
425 	atomic_add_16(&nx_netif_vpna_gencnt, 1);
426 	nifna->nifna_gencnt = nx_netif_vpna_gencnt;
427 	atomic_bitset_32(&na->na_flags, NAF_ACTIVE);
428 	return 0;
429 }
430 
431 static int
netif_vp_na_activate_off(struct nexus_adapter * na)432 netif_vp_na_activate_off(struct nexus_adapter *na)
433 {
434 	errno_t err;
435 	struct nexus_netif_adapter *nifna;
436 	struct nx_netif *nif;
437 
438 	if (!NA_IS_ACTIVE(na)) {
439 		DTRACE_SKYWALK1(already__off, struct nexus_adapter *, na);
440 		return 0;
441 	}
442 	nifna = NIFNA(na);
443 	nif = nifna->nifna_netif;
444 	err = nx_netif_flow_remove(nif, nifna->nifna_flow);
445 	VERIFY(err == 0);
446 
447 	nifna->nifna_flow = NULL;
448 	if (NETIF_IS_LOW_LATENCY(nif)) {
449 		netif_hwna_teardown(nif);
450 	}
451 	atomic_bitclear_32(&na->na_flags, NAF_ACTIVE);
452 	return 0;
453 }
454 
455 static int
netif_vp_na_activate(struct nexus_adapter * na,na_activate_mode_t mode)456 netif_vp_na_activate(struct nexus_adapter *na, na_activate_mode_t mode)
457 {
458 	errno_t err;
459 
460 	ASSERT(na->na_type == NA_NETIF_VP);
461 	if (mode == NA_ACTIVATE_MODE_ON) {
462 		err = netif_vp_na_activate_on(na);
463 	} else {
464 		err = netif_vp_na_activate_off(na);
465 	}
466 	SK_DF(SK_VERB_VP, "na \"%s\" (0x%llx) %s err %d", na->na_name,
467 	    SK_KVA(na), na_activate_mode2str(mode), err);
468 	return err;
469 }
470 
471 /*
472  * XXX
473  * The native path sends to the dev ring directly, bypassing aqm.
474  * This is ok since this is only used by llw now. This will need to
475  * change when we add native support for filters.
476  */
477 static int
netif_vp_send_pkt_chain_low_latency(struct nexus_netif_adapter * dev_nifna,struct __kern_packet * pkt_chain,struct proc * p)478 netif_vp_send_pkt_chain_low_latency(struct nexus_netif_adapter *dev_nifna,
479     struct __kern_packet *pkt_chain, struct proc *p)
480 {
481 	struct __kern_packet *pkt = pkt_chain, *next;
482 	struct nexus_adapter *na = &dev_nifna->nifna_up;
483 	struct __kern_channel_ring *ring = &na->na_tx_rings[0];
484 	struct netif_stats *nifs = &dev_nifna->nifna_netif->nif_stats;
485 	sk_protect_t protect;
486 	slot_idx_t ktail, idx;
487 	uint32_t cnt;
488 	int err_stat = -1;
489 	errno_t err;
490 
491 	(void) kr_enter(ring, TRUE);
492 	protect = sk_sync_protect();
493 	if (__improbable(KR_DROP(ring))) {
494 		SK_ERR("ring is not ready");
495 		DTRACE_SKYWALK1(ring__drop, struct __kern_channel_ring *, ring);
496 		err_stat = NETIF_STATS_VP_DROP_DEV_RING_DISABLED;
497 		err = ENXIO;
498 		goto done;
499 	}
500 	idx = ring->ckr_rhead;
501 	ktail = ring->ckr_ktail;
502 	if (idx == ktail) {
503 		SK_ERR("no space to send");
504 		DTRACE_SKYWALK1(no__space, struct __kern_channel_ring *, ring);
505 		err_stat = NETIF_STATS_VP_DROP_DEV_RING_NO_SPACE;
506 		goto sync;
507 	}
508 	cnt = 0;
509 	while (pkt != NULL && idx != ktail) {
510 		struct __slot_desc *slot = &ring->ckr_ksds[idx];
511 
512 		next = pkt->pkt_nextpkt;
513 		pkt->pkt_nextpkt = NULL;
514 		netif_vp_dump_packet(pkt);
515 		err = netif_copy_or_attach_pkt(ring, slot, pkt);
516 		if (__probable(err == 0)) {
517 			cnt++;
518 			idx = SLOT_NEXT(idx, ring->ckr_lim);
519 		}
520 		pkt = next;
521 	}
522 	ring->ckr_rhead = idx;
523 	STATS_ADD(nifs, NETIF_STATS_VP_LL_ENQUEUED, cnt);
524 	DTRACE_SKYWALK2(ll__enqueued, struct __kern_channel_ring *, ring,
525 	    uint32_t, cnt);
526 sync:
527 	ring->ckr_khead_pre = ring->ckr_khead;
528 	err = ring->ckr_na_sync(ring, p, NA_SYNCF_SYNC_ONLY);
529 	if (err != 0 && err != EAGAIN) {
530 		SK_ERR("unexpected sync err %d", err);
531 		DTRACE_SKYWALK1(sync__failed, struct __kern_channel_ring *,
532 		    ring);
533 		err_stat = NETIF_STATS_VP_DROP_UNEXPECTED_ERR;
534 		goto done;
535 	}
536 	/*
537 	 * Verify that the driver has detached packets from the consumed slots.
538 	 */
539 	idx = ring->ckr_khead_pre;
540 	cnt = 0;
541 	while (idx != ring->ckr_khead) {
542 		struct __kern_slot_desc *ksd = KR_KSD(ring, idx);
543 
544 		cnt++;
545 		VERIFY(!KSD_VALID_METADATA(ksd));
546 		idx = SLOT_NEXT(idx, ring->ckr_lim);
547 	}
548 	ring->ckr_khead_pre = ring->ckr_khead;
549 	STATS_ADD(nifs, NETIF_STATS_VP_LL_SENT, cnt);
550 	DTRACE_SKYWALK2(ll__sent, struct __kern_channel_ring *, ring,
551 	    uint32_t, cnt);
552 	err = 0;
553 
554 done:
555 	sk_sync_unprotect(protect);
556 	kr_exit(ring);
557 
558 	/*
559 	 * Free all unsent packets.
560 	 */
561 	if (pkt != NULL) {
562 		int dropcnt;
563 
564 		nx_netif_free_packet_chain(pkt, &dropcnt);
565 		if (err_stat != -1) {
566 			STATS_ADD(nifs, err_stat, dropcnt);
567 		}
568 		STATS_ADD(nifs, NETIF_STATS_DROP, dropcnt);
569 	}
570 	return err;
571 }
572 
573 static int
netif_vp_send_pkt_chain_common(struct nexus_netif_adapter * dev_nifna,struct __kern_packet * pkt_chain,boolean_t compat)574 netif_vp_send_pkt_chain_common(struct nexus_netif_adapter *dev_nifna,
575     struct __kern_packet *pkt_chain, boolean_t compat)
576 {
577 	struct __kern_packet *pkt = pkt_chain, *next, *p;
578 	struct nx_netif *nif = dev_nifna->nifna_netif;
579 	struct netif_stats *nifs = &nif->nif_stats;
580 	ifnet_t ifp = nif->nif_ifp;
581 	struct mbuf *m;
582 	boolean_t drop;
583 	int cnt = 0;
584 	errno_t err;
585 
586 	while (pkt != NULL) {
587 		next = pkt->pkt_nextpkt;
588 		pkt->pkt_nextpkt = NULL;
589 		drop = FALSE;
590 
591 		if (compat) {
592 			m = nx_netif_pkt_to_mbuf(dev_nifna, pkt, NETIF_CONVERT_TX);
593 			if (m == NULL) {
594 				pkt = next;
595 				continue;
596 			}
597 			err = ifnet_enqueue_mbuf(ifp, m, FALSE, &drop);
598 		} else {
599 			p = nx_netif_pkt_to_pkt(dev_nifna, pkt, NETIF_CONVERT_TX);
600 			if (p == NULL) {
601 				pkt = next;
602 				continue;
603 			}
604 			err = ifnet_enqueue_pkt(ifp, p, FALSE, &drop);
605 		}
606 		if (err != 0) {
607 			SK_ERR("enqueue failed: %d", err);
608 			STATS_INC(nifs, NETIF_STATS_VP_ENQUEUE_FAILED);
609 			if (drop) {
610 				STATS_INC(nifs, NETIF_STATS_DROP);
611 			}
612 			DTRACE_SKYWALK2(enqueue__failed,
613 			    struct nexus_netif_adapter *, dev_nifna,
614 			    boolean_t, drop);
615 		} else {
616 			STATS_INC(nifs, NETIF_STATS_VP_ENQUEUED);
617 			cnt++;
618 		}
619 		pkt = next;
620 	}
621 	if (cnt > 0) {
622 		ifnet_start(ifp);
623 	}
624 	return 0;
625 }
626 
627 static int
netif_vp_send_pkt_chain(struct nexus_netif_adapter * dev_nifna,struct __kern_packet * pkt_chain,struct proc * p)628 netif_vp_send_pkt_chain(struct nexus_netif_adapter *dev_nifna,
629     struct __kern_packet *pkt_chain, struct proc *p)
630 {
631 	struct nexus_adapter *na = &dev_nifna->nifna_up;
632 
633 	if (NETIF_IS_LOW_LATENCY(dev_nifna->nifna_netif)) {
634 		return netif_vp_send_pkt_chain_low_latency(dev_nifna,
635 		           pkt_chain, p);
636 	}
637 	if (na->na_type == NA_NETIF_DEV) {
638 		return netif_vp_send_pkt_chain_common(dev_nifna, pkt_chain, FALSE);
639 	}
640 	ASSERT(na->na_type == NA_NETIF_COMPAT_DEV);
641 	return netif_vp_send_pkt_chain_common(dev_nifna, pkt_chain, TRUE);
642 }
643 
644 SK_NO_INLINE_ATTRIBUTE
645 static boolean_t
validate_packet(struct nexus_netif_adapter * nifna,struct __kern_packet * pkt)646 validate_packet(struct nexus_netif_adapter *nifna, struct __kern_packet *pkt)
647 {
648 	struct nx_netif *nif = nifna->nifna_netif;
649 
650 	VERIFY(pkt->pkt_nextpkt == NULL);
651 
652 	if (nx_netif_vp_accept_all != 0) {
653 		return TRUE;
654 	}
655 	if (outbound_check == 0 ||
656 	    (NETIF_IS_LOW_LATENCY(nif) &&
657 	    outbound_check != OUTBOUND_CHECK_FORCED)) {
658 		return TRUE;
659 	}
660 	if (!nx_netif_validate_macaddr(nif, pkt, NETIF_FLOW_OUTBOUND)) {
661 		return FALSE;
662 	}
663 	if (!nx_netif_flow_match(nif, pkt, nifna->nifna_flow,
664 	    NETIF_FLOW_OUTBOUND)) {
665 		return FALSE;
666 	}
667 	return TRUE;
668 }
669 
670 static int
netif_vp_na_txsync(struct __kern_channel_ring * kring,struct proc * p,uint32_t flags)671 netif_vp_na_txsync(struct __kern_channel_ring *kring, struct proc *p,
672     uint32_t flags)
673 {
674 #pragma unused(flags)
675 	kern_channel_slot_t last_slot = NULL, slot = NULL;
676 	struct __kern_packet *head = NULL, **tailp = &head, *pkt;
677 	struct nexus_netif_adapter *nifna, *dev_nifna;
678 	struct nx_netif *nif;
679 	struct netif_stats *nifs;
680 	kern_packet_t ph;
681 	errno_t err;
682 	int cnt = 0;
683 
684 	nifna = NIFNA(KRNA(kring));
685 	nif = nifna->nifna_netif;
686 	nifs = &nif->nif_stats;
687 	for (;;) {
688 		slot = kern_channel_get_next_slot(kring, slot, NULL);
689 		if (slot == NULL) {
690 			break;
691 		}
692 		ph = kern_channel_slot_get_packet(kring, slot);
693 		if (__improbable(ph == 0)) {
694 			SK_ERR("packet got dropped by internalize");
695 			STATS_INC(nifs, NETIF_STATS_VP_DROP_INTERNALIZE_FAIL);
696 			DTRACE_SKYWALK2(bad__slot, struct __kern_channel_ring *,
697 			    kring, kern_channel_slot_t, slot);
698 			last_slot = slot;
699 			continue;
700 		}
701 		pkt = SK_PTR_ADDR_KPKT(ph);
702 		if (__improbable(pkt->pkt_length == 0)) {
703 			SK_ERR("dropped zero length packet");
704 			STATS_INC(nifs, NETIF_STATS_VP_BAD_PKT_LEN);
705 			DTRACE_SKYWALK2(bad__slot, struct __kern_channel_ring *,
706 			    kring, kern_channel_slot_t, slot);
707 			last_slot = slot;
708 			continue;
709 		}
710 		err = kern_channel_slot_detach_packet(kring, slot, ph);
711 		VERIFY(err == 0);
712 
713 		/* packet needs to be finalized after detach */
714 		err = kern_packet_finalize(ph);
715 		VERIFY(err == 0);
716 		last_slot = slot;
717 
718 		if (NA_CHANNEL_EVENT_ATTACHED(KRNA(kring))) {
719 			__packet_set_tx_nx_port(SK_PKT2PH(pkt),
720 			    KRNA(kring)->na_nx_port, nifna->nifna_gencnt);
721 		}
722 
723 		if (validate_packet(nifna, pkt)) {
724 			nx_netif_snoop(nif, pkt, FALSE);
725 			cnt++;
726 			*tailp = pkt;
727 			tailp = &pkt->pkt_nextpkt;
728 		} else {
729 			nx_netif_free_packet(pkt);
730 		}
731 	}
732 	if (cnt == 0) {
733 		STATS_INC(nifs, NETIF_STATS_VP_SYNC_NO_PKTS);
734 		DTRACE_SKYWALK2(no__data, struct nexus_netif_adapter *, nifna,
735 		    struct __kern_channel_ring *, kring);
736 		return 0;
737 	}
738 	DTRACE_SKYWALK4(injected, struct nexus_netif_adapter *, nifna,
739 	    struct __kern_channel_ring *, kring, struct __kern_packet *, head,
740 	    int, cnt);
741 	if (last_slot != NULL) {
742 		kern_channel_advance_slot(kring, last_slot);
743 	}
744 
745 	dev_nifna = NIFNA(nx_port_get_na(KRNA(kring)->na_nx,
746 	    NEXUS_PORT_NET_IF_DEV));
747 
748 	err = netif_vp_send_pkt_chain(dev_nifna, head, p);
749 	if (err != 0) {
750 		SK_ERR("send failed: %d\n", err);
751 	}
752 	return 0;
753 }
754 
755 static int
netif_vp_na_rxsync(struct __kern_channel_ring * kring,struct proc * p,uint32_t flags)756 netif_vp_na_rxsync(struct __kern_channel_ring *kring, struct proc *p,
757     uint32_t flags)
758 {
759 #pragma unused(p, flags)
760 	(void) kr_reclaim(kring);
761 	return 0;
762 }
763 
764 static int
netif_vp_na_krings_create(struct nexus_adapter * na,struct kern_channel * ch)765 netif_vp_na_krings_create(struct nexus_adapter *na, struct kern_channel *ch)
766 {
767 	ASSERT(na->na_type == NA_NETIF_VP);
768 	return na_rings_mem_setup(na, FALSE, ch);
769 }
770 
771 
772 /* na_krings_delete callback for flow switch ports. */
773 static void
netif_vp_na_krings_delete(struct nexus_adapter * na,struct kern_channel * ch,boolean_t defunct)774 netif_vp_na_krings_delete(struct nexus_adapter *na, struct kern_channel *ch,
775     boolean_t defunct)
776 {
777 	ASSERT(na->na_type == NA_NETIF_VP);
778 	na_rings_mem_teardown(na, ch, defunct);
779 }
780 
781 static int
netif_vp_region_params_setup(struct nexus_adapter * na,struct skmem_region_params * srp,struct kern_pbufpool ** tx_pp)782 netif_vp_region_params_setup(struct nexus_adapter *na,
783     struct skmem_region_params *srp, struct kern_pbufpool **tx_pp)
784 {
785 #pragma unused (tx_pp)
786 	uint32_t max_mtu;
787 	uint32_t buf_sz, buf_cnt, nslots, afslots, evslots, totalrings;
788 	struct nexus_adapter *devna;
789 	struct kern_nexus *nx;
790 	struct nx_netif *nif;
791 	int err, i;
792 
793 	for (i = 0; i < SKMEM_REGIONS; i++) {
794 		srp[i] = *skmem_get_default(i);
795 	}
796 	totalrings = na_get_nrings(na, NR_TX) + na_get_nrings(na, NR_RX) +
797 	    na_get_nrings(na, NR_A) + na_get_nrings(na, NR_F) +
798 	    na_get_nrings(na, NR_EV);
799 
800 	srp[SKMEM_REGION_SCHEMA].srp_r_obj_size =
801 	    (uint32_t)CHANNEL_SCHEMA_SIZE(totalrings);
802 	srp[SKMEM_REGION_SCHEMA].srp_r_obj_cnt = totalrings;
803 	skmem_region_params_config(&srp[SKMEM_REGION_SCHEMA]);
804 
805 	srp[SKMEM_REGION_RING].srp_r_obj_size =
806 	    sizeof(struct __user_channel_ring);
807 	srp[SKMEM_REGION_RING].srp_r_obj_cnt = totalrings;
808 	skmem_region_params_config(&srp[SKMEM_REGION_RING]);
809 
810 	/* USD regions need to be writable to support user packet pool */
811 	srp[SKMEM_REGION_TXAUSD].srp_cflags &= ~SKMEM_REGION_CR_UREADONLY;
812 	srp[SKMEM_REGION_RXFUSD].srp_cflags &= ~SKMEM_REGION_CR_UREADONLY;
813 
814 	nslots = na_get_nslots(na, NR_TX);
815 	afslots = na_get_nslots(na, NR_A);
816 	evslots = na_get_nslots(na, NR_EV);
817 	srp[SKMEM_REGION_TXAKSD].srp_r_obj_size =
818 	    MAX(MAX(nslots, afslots), evslots) * SLOT_DESC_SZ;
819 	srp[SKMEM_REGION_TXAKSD].srp_r_obj_cnt =
820 	    na_get_nrings(na, NR_TX) + na_get_nrings(na, NR_A) +
821 	    na_get_nrings(na, NR_EV);
822 	skmem_region_params_config(&srp[SKMEM_REGION_TXAKSD]);
823 
824 	/* USD and KSD objects share the same size and count */
825 	srp[SKMEM_REGION_TXAUSD].srp_r_obj_size =
826 	    srp[SKMEM_REGION_TXAKSD].srp_r_obj_size;
827 	srp[SKMEM_REGION_TXAUSD].srp_r_obj_cnt =
828 	    srp[SKMEM_REGION_TXAKSD].srp_r_obj_cnt;
829 	skmem_region_params_config(&srp[SKMEM_REGION_TXAUSD]);
830 
831 	/*
832 	 * Since the rx/free slots share the same region and cache,
833 	 * we will use the same object size for both types of slots.
834 	 */
835 	nslots = na_get_nslots(na, NR_RX);
836 	afslots = na_get_nslots(na, NR_F);
837 	srp[SKMEM_REGION_RXFKSD].srp_r_obj_size =
838 	    MAX(nslots, afslots) * SLOT_DESC_SZ;
839 	srp[SKMEM_REGION_RXFKSD].srp_r_obj_cnt =
840 	    na_get_nrings(na, NR_RX) + na_get_nrings(na, NR_F);
841 	skmem_region_params_config(&srp[SKMEM_REGION_RXFKSD]);
842 
843 	/* USD and KSD objects share the same size and count */
844 	srp[SKMEM_REGION_RXFUSD].srp_r_obj_size =
845 	    srp[SKMEM_REGION_RXFKSD].srp_r_obj_size;
846 	srp[SKMEM_REGION_RXFUSD].srp_r_obj_cnt =
847 	    srp[SKMEM_REGION_RXFKSD].srp_r_obj_cnt;
848 	skmem_region_params_config(&srp[SKMEM_REGION_RXFUSD]);
849 
850 	/*
851 	 * No need to create our own buffer pool if we can share the device's
852 	 * pool. We don't support sharing split pools to user space.
853 	 */
854 	nx = na->na_nx;
855 	nif = nx->nx_arg;
856 	if (vp_zerocopy != 0 && NETIF_IS_LOW_LATENCY(nif) &&
857 	    nx->nx_tx_pp != NULL && (nx->nx_rx_pp == NULL ||
858 	    nx->nx_tx_pp == nx->nx_rx_pp) && !PP_KERNEL_ONLY(nx->nx_tx_pp)) {
859 		struct kern_pbufpool *pp = nx->nx_tx_pp;
860 
861 		if (nif->nif_hw_ch_refcnt != 0) {
862 			SK_ERR("only one channel is supported for zero copy");
863 			return ENOTSUP;
864 		}
865 		SK_DF(SK_VERB_VP, "sharing %s's pool", if_name(na->na_ifp));
866 
867 		/*
868 		 * These types need to be initialized otherwise some assertions
869 		 * skmem_arena_create_for_nexus() will fail.
870 		 */
871 		srp[SKMEM_REGION_UMD].srp_md_type = pp->pp_md_type;
872 		srp[SKMEM_REGION_UMD].srp_md_subtype = pp->pp_md_subtype;
873 		srp[SKMEM_REGION_KMD].srp_md_type = pp->pp_md_type;
874 		srp[SKMEM_REGION_KMD].srp_md_subtype = pp->pp_md_subtype;
875 		*tx_pp = nx->nx_tx_pp;
876 		return 0;
877 	}
878 
879 	devna = nx_port_get_na(nx, NEXUS_PORT_NET_IF_DEV);
880 	ASSERT(devna != NULL);
881 	if (devna->na_type == NA_NETIF_DEV) {
882 		/*
883 		 * For native devices, use the driver's buffer size
884 		 */
885 		ASSERT(nx->nx_rx_pp != NULL);
886 		ASSERT(nx->nx_tx_pp != NULL);
887 		buf_sz = PP_BUF_SIZE_DEF(nx->nx_tx_pp);
888 	} else {
889 		if ((err = nx_netif_get_max_mtu(na->na_ifp, &max_mtu)) != 0) {
890 			/*
891 			 * If the driver doesn't support SIOCGIFDEVMTU, use the
892 			 * default MTU size.
893 			 */
894 			max_mtu = ifnet_mtu(na->na_ifp);
895 			err = 0;
896 		}
897 		/* max_mtu does not include the L2 header */
898 		buf_sz = MAX(max_mtu + sizeof(struct ether_vlan_header), 2048);
899 	}
900 	buf_cnt = vp_pool_size;
901 	pp_regions_params_adjust(srp, NEXUS_META_TYPE_PACKET,
902 	    NEXUS_META_SUBTYPE_RAW, buf_cnt, 1, buf_sz, 0, buf_cnt, 0,
903 	    PP_REGION_CONFIG_BUF_IODIR_BIDIR |
904 	    PP_REGION_CONFIG_MD_MAGAZINE_ENABLE);
905 
906 	nx_netif_vp_region_params_adjust(na, srp);
907 	return 0;
908 }
909 
910 static int
netif_vp_na_mem_new(struct kern_nexus * nx,struct nexus_adapter * na)911 netif_vp_na_mem_new(struct kern_nexus *nx, struct nexus_adapter *na)
912 {
913 #pragma unused(nx)
914 	struct skmem_region_params srp[SKMEM_REGIONS];
915 	struct kern_pbufpool *tx_pp = NULL;
916 	int err;
917 
918 	err = netif_vp_region_params_setup(na, srp, &tx_pp);
919 	if (err != 0) {
920 		return err;
921 	}
922 	na->na_arena = skmem_arena_create_for_nexus(na, srp,
923 	    tx_pp != NULL ? &tx_pp : NULL, NULL,
924 	    0, &nx->nx_adv, &err);
925 	ASSERT(na->na_arena != NULL || err != 0);
926 	return err;
927 }
928 
929 static void
netif_vp_na_dtor(struct nexus_adapter * na)930 netif_vp_na_dtor(struct nexus_adapter *na)
931 {
932 	struct kern_nexus *nx = na->na_nx;
933 	struct nx_netif *nif = NX_NETIF_PRIVATE(nx);
934 	struct nexus_netif_adapter *nifna = NIFNA(na);
935 
936 	NETIF_WLOCK(nif);
937 	(void) nx_port_unbind(nx, na->na_nx_port);
938 	nx_port_free(nx, na->na_nx_port);
939 	nif->nif_vp_cnt--;
940 	if (na->na_ifp != NULL) {
941 		ifnet_decr_iorefcnt(na->na_ifp);
942 		na->na_ifp = NULL;
943 	}
944 	if (nifna->nifna_netif != NULL) {
945 		nx_netif_release(nifna->nifna_netif);
946 		nifna->nifna_netif = NULL;
947 	}
948 	NETIF_WUNLOCK(nif);
949 	SK_DF(SK_VERB_VP, "na \"%s\" (0x%llx)", na->na_name, SK_KVA(na));
950 }
951 
952 int
netif_vp_na_create(struct kern_nexus * nx,struct chreq * chr,struct nexus_adapter ** nap)953 netif_vp_na_create(struct kern_nexus *nx, struct chreq *chr,
954     struct nexus_adapter **nap)
955 {
956 	struct nx_netif *nif = NX_NETIF_PRIVATE(nx);
957 	struct nxprov_params *nxp = NX_PROV(nx)->nxprov_params;
958 	struct nexus_adapter *na = NULL;
959 	struct nexus_netif_adapter *nifna;
960 	uint32_t slots;
961 	int err;
962 
963 	NETIF_WLOCK_ASSERT_HELD(nif);
964 	if (nif->nif_ifp == NULL) {
965 		SK_ERR("ifnet not yet attached");
966 		return ENXIO;
967 	}
968 	ASSERT((chr->cr_mode & CHMODE_KERNEL) == 0);
969 	if ((chr->cr_mode & CHMODE_USER_PACKET_POOL) == 0) {
970 		SK_ERR("user packet pool required");
971 		return EINVAL;
972 	}
973 	/*
974 	 * No locking needed while checking for the initialized bit because
975 	 * if this were not set, no other codepaths would modify the flags.
976 	 */
977 	if ((nif->nif_flow_flags & NETIF_FLOW_FLAG_INITIALIZED) == 0) {
978 		SK_ERR("demux vp not supported");
979 		return ENOTSUP;
980 	}
981 	na = (struct nexus_adapter *)na_netif_alloc(Z_WAITOK);
982 	nifna = NIFNA(na);
983 	nifna->nifna_netif = nif;
984 	nx_netif_retain(nif);
985 	nifna->nifna_flow = NULL;
986 
987 	(void) snprintf(na->na_name, sizeof(na->na_name),
988 	    "netif_vp:%d", chr->cr_port);
989 	uuid_generate_random(na->na_uuid);
990 
991 	na_set_nrings(na, NR_TX, nxp->nxp_tx_rings);
992 	na_set_nrings(na, NR_RX, nxp->nxp_rx_rings);
993 	/*
994 	 * If the packet pool is configured to be multi-buflet, then we
995 	 * need 2 pairs of alloc/free rings(for packet and buflet).
996 	 */
997 	na_set_nrings(na, NR_A, ((nxp->nxp_max_frags > 1) &&
998 	    (sk_channel_buflet_alloc != 0)) ? 2 : 1);
999 
1000 	slots = vp_tx_slots != 0 ? vp_tx_slots :
1001 	    NX_DOM(nx)->nxdom_tx_slots.nb_def;
1002 	na_set_nslots(na, NR_TX, slots);
1003 
1004 	slots = vp_rx_slots != 0 ? vp_rx_slots :
1005 	    NX_DOM(nx)->nxdom_rx_slots.nb_def;
1006 	na_set_nslots(na, NR_RX, slots);
1007 
1008 	na_set_nslots(na, NR_A, NETIF_DEMUX_ALLOC_SLOTS);
1009 	ASSERT(na_get_nrings(na, NR_TX) <= NX_DOM(nx)->nxdom_tx_rings.nb_max);
1010 	ASSERT(na_get_nrings(na, NR_RX) <= NX_DOM(nx)->nxdom_rx_rings.nb_max);
1011 	ASSERT(na_get_nslots(na, NR_TX) <= NX_DOM(nx)->nxdom_tx_slots.nb_max);
1012 	ASSERT(na_get_nslots(na, NR_RX) <= NX_DOM(nx)->nxdom_rx_slots.nb_max);
1013 
1014 	atomic_bitset_32(&na->na_flags, NAF_USER_PKT_POOL);
1015 
1016 	if (chr->cr_mode & CHMODE_EVENT_RING) {
1017 		na_set_nrings(na, NR_EV, NX_NETIF_EVENT_RING_NUM);
1018 		na_set_nslots(na, NR_EV, NX_NETIF_EVENT_RING_SIZE);
1019 		atomic_bitset_32(&na->na_flags, NAF_EVENT_RING);
1020 		na->na_channel_event_notify = netif_vp_na_channel_event_notify;
1021 	}
1022 
1023 	na->na_nx_port = chr->cr_port;
1024 	na->na_type = NA_NETIF_VP;
1025 	na->na_free = na_netif_free;
1026 	na->na_dtor = netif_vp_na_dtor;
1027 	na->na_activate = netif_vp_na_activate;
1028 	na->na_txsync = netif_vp_na_txsync;
1029 	na->na_rxsync = netif_vp_na_rxsync;
1030 	na->na_krings_create = netif_vp_na_krings_create;
1031 	na->na_krings_delete = netif_vp_na_krings_delete;
1032 	na->na_special = NULL;
1033 	na->na_ifp = nif->nif_ifp;
1034 	ifnet_incr_iorefcnt(na->na_ifp);
1035 
1036 	*(nexus_stats_type_t *)(uintptr_t)&na->na_stats_type =
1037 	    NEXUS_STATS_TYPE_INVALID;
1038 
1039 	/* other fields are set in the common routine */
1040 	na_attach_common(na, nx, &nx_netif_prov_s);
1041 
1042 	err = netif_vp_na_mem_new(nx, na);
1043 	if (err != 0) {
1044 		ASSERT(na->na_arena == NULL);
1045 		goto err;
1046 	}
1047 
1048 	*(uint32_t *)(uintptr_t)&na->na_flowadv_max = nxp->nxp_flowadv_max;
1049 	ASSERT(na->na_flowadv_max == 0 ||
1050 	    skmem_arena_nexus(na->na_arena)->arn_flowadv_obj != NULL);
1051 
1052 	nif->nif_vp_cnt++;
1053 	*nap = na;
1054 	return 0;
1055 
1056 err:
1057 	if (na != NULL) {
1058 		if (na->na_ifp != NULL) {
1059 			ifnet_decr_iorefcnt(na->na_ifp);
1060 			na->na_ifp = NULL;
1061 		}
1062 		if (na->na_arena != NULL) {
1063 			skmem_arena_release(na->na_arena);
1064 			na->na_arena = NULL;
1065 		}
1066 		if (nifna->nifna_netif != NULL) {
1067 			nx_netif_release(nifna->nifna_netif);
1068 			nifna->nifna_netif = NULL;
1069 		}
1070 		NA_FREE(na);
1071 	}
1072 	SK_ERR("VP NA creation failed, err(%d)", err);
1073 	return err;
1074 }
1075 
1076 static int
netif_vp_na_channel_event_notify(struct nexus_adapter * vpna,struct __kern_channel_event * ev,uint16_t ev_len)1077 netif_vp_na_channel_event_notify(struct nexus_adapter *vpna,
1078     struct __kern_channel_event *ev, uint16_t ev_len)
1079 {
1080 	int err;
1081 	char *baddr;
1082 	kern_packet_t ph;
1083 	kern_buflet_t buf;
1084 	sk_protect_t protect;
1085 	kern_channel_slot_t slot;
1086 	struct __kern_packet *vpna_pkt = NULL;
1087 	struct __kern_channel_event_metadata *emd;
1088 	struct __kern_channel_ring *ring = &vpna->na_event_rings[0];
1089 	struct netif_stats *nifs = &NIFNA(vpna)->nifna_netif->nif_stats;
1090 
1091 	if (__improbable(!NA_IS_ACTIVE(vpna))) {
1092 		STATS_INC(nifs, NETIF_STATS_EV_DROP_NA_INACTIVE);
1093 		err = ENXIO;
1094 		goto error;
1095 	}
1096 	if (__improbable(NA_IS_DEFUNCT(vpna))) {
1097 		STATS_INC(nifs, NETIF_STATS_EV_DROP_NA_DEFUNCT);
1098 		err = ENXIO;
1099 		goto error;
1100 	}
1101 	if (!NA_CHANNEL_EVENT_ATTACHED(vpna)) {
1102 		STATS_INC(nifs, NETIF_STATS_EV_DROP_KEVENT_INACTIVE);
1103 		err = ENXIO;
1104 		goto error;
1105 	}
1106 	if (__improbable(KR_DROP(ring))) {
1107 		STATS_INC(nifs, NETIF_STATS_EV_DROP_KRDROP_MODE);
1108 		err = ENXIO;
1109 		goto error;
1110 	}
1111 	vpna_pkt = nx_netif_alloc_packet(ring->ckr_pp, ev_len, &ph);
1112 	if (__improbable(vpna_pkt == NULL)) {
1113 		STATS_INC(nifs, NETIF_STATS_EV_DROP_NOMEM_PKT);
1114 		err = ENOMEM;
1115 		goto error;
1116 	}
1117 	buf = __packet_get_next_buflet(ph, NULL);
1118 	baddr = __buflet_get_data_address(buf);
1119 	emd = (struct __kern_channel_event_metadata *)(void *)baddr;
1120 	emd->emd_etype = CHANNEL_EVENT_PACKET_TRANSMIT_STATUS;
1121 	emd->emd_nevents = 1;
1122 	bcopy(ev, (baddr + __KERN_CHANNEL_EVENT_OFFSET), ev_len);
1123 	err = __buflet_set_data_length(buf,
1124 	    (ev_len + __KERN_CHANNEL_EVENT_OFFSET));
1125 	VERIFY(err == 0);
1126 	err = __packet_finalize(ph);
1127 	VERIFY(err == 0);
1128 	kr_enter(ring, TRUE);
1129 	protect = sk_sync_protect();
1130 	slot = kern_channel_get_next_slot(ring, NULL, NULL);
1131 	if (slot == NULL) {
1132 		sk_sync_unprotect(protect);
1133 		kr_exit(ring);
1134 		STATS_INC(nifs, NETIF_STATS_EV_DROP_KRSPACE);
1135 		err = ENOSPC;
1136 		goto error;
1137 	}
1138 	err = kern_channel_slot_attach_packet(ring, slot, ph);
1139 	VERIFY(err == 0);
1140 	vpna_pkt = NULL;
1141 	kern_channel_advance_slot(ring, slot);
1142 	sk_sync_unprotect(protect);
1143 	kr_exit(ring);
1144 	kern_channel_event_notify(&vpna->na_tx_rings[0]);
1145 	STATS_INC(nifs, NETIF_STATS_EV_SENT);
1146 	return 0;
1147 
1148 error:
1149 	ASSERT(err != 0);
1150 	if (vpna_pkt != NULL) {
1151 		nx_netif_free_packet(vpna_pkt);
1152 	}
1153 	STATS_INC(nifs, NETIF_STATS_EV_DROP);
1154 	return err;
1155 }
1156 
1157 static inline struct nexus_adapter *
nx_netif_find_port_vpna(struct nx_netif * netif,uint32_t nx_port_id)1158 nx_netif_find_port_vpna(struct nx_netif *netif, uint32_t nx_port_id)
1159 {
1160 	struct kern_nexus *nx = netif->nif_nx;
1161 	struct nexus_adapter *na = NULL;
1162 	nexus_port_t port;
1163 	uint16_t gencnt;
1164 
1165 	PKT_DECOMPOSE_NX_PORT_ID(nx_port_id, port, gencnt);
1166 	if (port < NEXUS_PORT_NET_IF_CLIENT) {
1167 		SK_ERR("non VPNA port");
1168 		return NULL;
1169 	}
1170 	if (__improbable(!nx_port_is_valid(nx, port))) {
1171 		SK_ERR("%s[%d] port no longer valid",
1172 		    if_name(netif->nif_ifp), port);
1173 		return NULL;
1174 	}
1175 	na = nx_port_get_na(nx, port);
1176 	if (na != NULL && NIFNA(na)->nifna_gencnt != gencnt) {
1177 		return NULL;
1178 	}
1179 	return na;
1180 }
1181 
1182 errno_t
netif_vp_na_channel_event(struct nx_netif * nif,uint32_t nx_port_id,struct __kern_channel_event * event,uint16_t event_len)1183 netif_vp_na_channel_event(struct nx_netif *nif, uint32_t nx_port_id,
1184     struct __kern_channel_event *event, uint16_t event_len)
1185 {
1186 	int err = 0;
1187 	struct nexus_adapter *netif_vpna;
1188 	struct netif_stats *nifs = &nif->nif_stats;
1189 
1190 	NETIF_RLOCK(nif);
1191 	if (!NETIF_IS_LOW_LATENCY(nif)) {
1192 		err = ENOTSUP;
1193 		goto error;
1194 	}
1195 	if (__improbable(nif->nif_vp_cnt == 0)) {
1196 		STATS_INC(nifs, NETIF_STATS_EV_DROP_NO_VPNA);
1197 		err = ENXIO;
1198 		goto error;
1199 	}
1200 	netif_vpna = nx_netif_find_port_vpna(nif, nx_port_id);
1201 	if (__improbable(netif_vpna == NULL)) {
1202 		err = ENXIO;
1203 		STATS_INC(nifs, NETIF_STATS_EV_DROP_DEMUX_ERR);
1204 		goto error;
1205 	}
1206 	if (__improbable(netif_vpna->na_channel_event_notify == NULL)) {
1207 		err = ENOTSUP;
1208 		STATS_INC(nifs, NETIF_STATS_EV_DROP_EV_VPNA_NOTSUP);
1209 		goto error;
1210 	}
1211 	err = netif_vpna->na_channel_event_notify(netif_vpna, event, event_len);
1212 	NETIF_RUNLOCK(nif);
1213 	return err;
1214 
1215 error:
1216 	STATS_INC(nifs, NETIF_STATS_EV_DROP);
1217 	NETIF_RUNLOCK(nif);
1218 	return err;
1219 }
1220