Print this page
11490 SRS ring polling disabled for VLANs
11491 Want DLS bypass for VLAN traffic
11492 add VLVF bypass to ixgbe core
2869 duplicate packets with vnics over aggrs
11489 DLS stat delete and aggr kstat can deadlock
Portions contributed by: Theo Schlossnagle <jesus@omniti.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Dan McDonald <danmcd@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/dls/dls.c
+++ new/usr/src/uts/common/io/dls/dls.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 * Copyright 2012, Nexenta Systems, Inc. All rights reserved.
25 25 */
26 26
27 27 /*
28 28 * Copyright 2019 Joyent, Inc.
29 29 */
30 30
31 31 /*
32 32 * Data-Link Services Module
33 33 */
34 34
35 35 #include <sys/strsun.h>
36 36 #include <sys/vlan.h>
37 37 #include <sys/dld_impl.h>
38 38 #include <sys/mac_client_priv.h>
39 39
40 40 int
41 41 dls_open(dls_link_t *dlp, dls_dl_handle_t ddh, dld_str_t *dsp)
42 42 {
43 43 zoneid_t zid = getzoneid();
44 44 boolean_t local;
45 45 int err;
46 46
47 47 /*
48 48 * Check whether this client belongs to the zone of this dlp. Note that
49 49 * a global zone client is allowed to open a local zone dlp.
50 50 */
51 51 if (zid != GLOBAL_ZONEID && dlp->dl_zid != zid)
52 52 return (ENOENT);
53 53
54 54 /*
55 55 * mac_start() is required for non-legacy MACs to show accurate
56 56 * kstats even before the interface is brought up. For legacy
57 57 * drivers, this is not needed. Further, calling mac_start() for
58 58 * legacy drivers would make the shared-lower-stream to stay in
59 59 * the DL_IDLE state, which in turn causes performance regression.
60 60 */
61 61 if (!mac_capab_get(dlp->dl_mh, MAC_CAPAB_LEGACY, NULL) &&
62 62 ((err = mac_start(dlp->dl_mh)) != 0)) {
63 63 return (err);
64 64 }
65 65
66 66 local = (zid == dlp->dl_zid);
67 67 dlp->dl_zone_ref += (local ? 1 : 0);
68 68
69 69 /*
70 70 * Cache a copy of the MAC interface handle, a pointer to the
71 71 * immutable MAC info.
72 72 */
73 73 dsp->ds_dlp = dlp;
74 74 dsp->ds_mh = dlp->dl_mh;
75 75 dsp->ds_mch = dlp->dl_mch;
76 76 dsp->ds_mip = dlp->dl_mip;
77 77 dsp->ds_ddh = ddh;
78 78 dsp->ds_local = local;
79 79
80 80 ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
81 81 return (0);
82 82 }
83 83
84 84 void
85 85 dls_close(dld_str_t *dsp)
86 86 {
87 87 dls_link_t *dlp = dsp->ds_dlp;
88 88 dls_multicst_addr_t *p;
89 89 dls_multicst_addr_t *nextp;
90 90
91 91 ASSERT(dsp->ds_datathr_cnt == 0);
92 92 ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
93 93
94 94 if (dsp->ds_local)
95 95 dlp->dl_zone_ref--;
96 96 dsp->ds_local = B_FALSE;
97 97
98 98 /*
99 99 * Walk the list of multicast addresses, disabling each at the MAC.
100 100 * Note that we must remove multicast address before
101 101 * mac_unicast_remove() (called by dls_active_clear()) because
102 102 * mac_multicast_remove() relies on the unicast flows on the mac
103 103 * client.
104 104 */
105 105 for (p = dsp->ds_dmap; p != NULL; p = nextp) {
106 106 (void) mac_multicast_remove(dsp->ds_mch, p->dma_addr);
107 107 nextp = p->dma_nextp;
108 108 kmem_free(p, sizeof (dls_multicst_addr_t));
109 109 }
110 110 dsp->ds_dmap = NULL;
111 111
112 112 dls_active_clear(dsp, B_TRUE);
113 113
114 114 /*
115 115 * If the dld_str_t is bound then unbind it.
116 116 */
117 117 if (dsp->ds_dlstate == DL_IDLE) {
118 118 dls_unbind(dsp);
119 119 dsp->ds_dlstate = DL_UNBOUND;
120 120 }
121 121
122 122 /*
123 123 * If the MAC has been set in promiscuous mode then disable it.
124 124 * This needs to be done before resetting ds_rx.
125 125 */
126 126 (void) dls_promisc(dsp, 0);
127 127
128 128 /*
129 129 * At this point we have cutoff inbound packet flow from the mac
130 130 * for this 'dsp'. The dls_link_remove above cut off packets meant
131 131 * for us and waited for upcalls to finish. Similarly the dls_promisc
132 132 * reset above waited for promisc callbacks to finish. Now we can
133 133 * safely reset ds_rx to NULL
134 134 */
135 135 dsp->ds_rx = NULL;
136 136 dsp->ds_rx_arg = NULL;
137 137
138 138 dsp->ds_dlp = NULL;
139 139
140 140 if (!mac_capab_get(dsp->ds_mh, MAC_CAPAB_LEGACY, NULL))
141 141 mac_stop(dsp->ds_mh);
142 142
143 143 /*
144 144 * Release our reference to the dls_link_t allowing that to be
145 145 * destroyed if there are no more dls_impl_t.
146 146 */
147 147 dls_link_rele(dlp);
148 148 }
149 149
150 150 int
151 151 dls_bind(dld_str_t *dsp, uint32_t sap)
152 152 {
153 153 uint32_t dls_sap;
154 154
155 155 ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
156 156
157 157 /*
158 158 * Check to see the value is legal for the media type.
159 159 */
160 160 if (!mac_sap_verify(dsp->ds_mh, sap, &dls_sap))
161 161 return (EINVAL);
162 162
163 163 if (dsp->ds_promisc & DLS_PROMISC_SAP)
↓ open down ↓ |
163 lines elided |
↑ open up ↑ |
164 164 dls_sap = DLS_SAP_PROMISC;
165 165
166 166 /*
167 167 * Set up the dld_str_t to mark it as able to receive packets.
168 168 */
169 169 dsp->ds_sap = sap;
170 170
171 171 /*
172 172 * The MAC layer does the VLAN demultiplexing and will only pass up
173 173 * untagged packets to non-promiscuous primary MAC clients. In order to
174 - * support the binding to the VLAN SAP which is required by DLPI, dls
174 + * support binding to the VLAN SAP, which is required by DLPI, DLS
175 175 * needs to get a copy of all tagged packets when the client binds to
176 176 * the VLAN SAP. We do this by registering a separate promiscuous
177 - * callback for each dls client binding to that SAP.
177 + * callback for each DLS client binding to that SAP.
178 178 *
179 179 * Note: even though there are two promiscuous handles in dld_str_t,
180 180 * ds_mph is for the regular promiscuous mode, ds_vlan_mph is the handle
181 - * to receive VLAN pkt when promiscuous mode is not on. Only one of
182 - * them can be non-NULL at the same time, to avoid receiving dup copies
183 - * of pkts.
181 + * to receive VLAN traffic when promiscuous mode is not on. Only one of
182 + * them can be non-NULL at the same time, to avoid receiving duplicate
183 + * copies of packets.
184 184 */
185 185 if (sap == ETHERTYPE_VLAN && dsp->ds_promisc == 0) {
186 186 int err;
187 187
188 188 if (dsp->ds_vlan_mph != NULL)
189 189 return (EINVAL);
190 190 err = mac_promisc_add(dsp->ds_mch,
191 191 MAC_CLIENT_PROMISC_ALL, dls_rx_vlan_promisc, dsp,
192 192 &dsp->ds_vlan_mph, MAC_PROMISC_FLAGS_NO_PHYS);
193 193
194 194 if (err == 0 && dsp->ds_nonip &&
195 195 dsp->ds_dlp->dl_nonip_cnt++ == 0)
196 196 mac_rx_bypass_disable(dsp->ds_mch);
197 197
198 198 return (err);
199 199 }
200 200
201 201 /*
202 202 * Now bind the dld_str_t by adding it into the hash table in the
203 203 * dls_link_t.
204 204 */
205 205 dls_link_add(dsp->ds_dlp, dls_sap, dsp);
206 206 if (dsp->ds_nonip && dsp->ds_dlp->dl_nonip_cnt++ == 0)
207 207 mac_rx_bypass_disable(dsp->ds_mch);
208 208
209 209 return (0);
210 210 }
211 211
212 212 void
213 213 dls_unbind(dld_str_t *dsp)
214 214 {
215 215 ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
216 216
217 217 if (dsp->ds_nonip && --dsp->ds_dlp->dl_nonip_cnt == 0)
218 218 mac_rx_bypass_enable(dsp->ds_mch);
219 219
220 220 /*
221 221 * A VLAN SAP does not actually add itself to the STREAM head today.
222 222 * While we initially set up a VLAN handle below, it's possible that
223 223 * something else will have come in and clobbered it.
224 224 */
225 225 if (dsp->ds_sap == ETHERTYPE_VLAN) {
226 226 if (dsp->ds_vlan_mph != NULL) {
227 227 mac_promisc_remove(dsp->ds_vlan_mph);
228 228 dsp->ds_vlan_mph = NULL;
229 229 }
230 230 return;
231 231 }
232 232
233 233 /*
234 234 * Unbind the dld_str_t by removing it from the hash table in the
235 235 * dls_link_t.
236 236 */
237 237 dls_link_remove(dsp->ds_dlp, dsp);
238 238 dsp->ds_sap = 0;
239 239 }
240 240
241 241 /*
242 242 * In order to prevent promiscuous-mode processing with dsp->ds_promisc
243 243 * set to inaccurate values, this function sets dsp->ds_promisc with new
244 244 * flags. For enabling (mac_promisc_add), the flags are set prior to the
245 245 * actual enabling. For disabling (mac_promisc_remove), the flags are set
246 246 * after the actual disabling.
247 247 */
248 248 int
249 249 dls_promisc(dld_str_t *dsp, uint32_t new_flags)
250 250 {
251 251 int err = 0;
252 252 uint32_t old_flags = dsp->ds_promisc;
253 253 mac_client_promisc_type_t mptype = MAC_CLIENT_PROMISC_ALL;
254 254
255 255 ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
256 256 ASSERT(!(new_flags & ~(DLS_PROMISC_SAP | DLS_PROMISC_MULTI |
257 257 DLS_PROMISC_PHYS)));
258 258
259 259 /*
260 260 * If the user has only requested DLS_PROMISC_MULTI then we need to make
261 261 * sure that they don't see all packets.
262 262 */
263 263 if (new_flags == DLS_PROMISC_MULTI)
264 264 mptype = MAC_CLIENT_PROMISC_MULTI;
265 265
266 266 if (dsp->ds_promisc == 0 && new_flags != 0) {
267 267 /*
268 268 * If only DLS_PROMISC_SAP, we don't turn on the
269 269 * physical promisc mode
270 270 */
271 271 dsp->ds_promisc = new_flags;
272 272 err = mac_promisc_add(dsp->ds_mch, mptype,
273 273 dls_rx_promisc, dsp, &dsp->ds_mph,
274 274 (new_flags != DLS_PROMISC_SAP) ? 0 :
275 275 MAC_PROMISC_FLAGS_NO_PHYS);
276 276 if (err != 0) {
277 277 dsp->ds_promisc = old_flags;
278 278 return (err);
279 279 }
280 280
281 281 /* Remove vlan promisc handle to avoid sending dup copy up */
282 282 if (dsp->ds_vlan_mph != NULL) {
283 283 mac_promisc_remove(dsp->ds_vlan_mph);
284 284 dsp->ds_vlan_mph = NULL;
285 285 }
286 286 } else if (dsp->ds_promisc != 0 && new_flags == 0) {
287 287 ASSERT(dsp->ds_mph != NULL);
288 288
289 289 mac_promisc_remove(dsp->ds_mph);
290 290 dsp->ds_promisc = new_flags;
291 291 dsp->ds_mph = NULL;
292 292
293 293 if (dsp->ds_sap == ETHERTYPE_VLAN &&
294 294 dsp->ds_dlstate != DL_UNBOUND) {
295 295 if (dsp->ds_vlan_mph != NULL)
296 296 return (EINVAL);
297 297 err = mac_promisc_add(dsp->ds_mch,
298 298 MAC_CLIENT_PROMISC_ALL, dls_rx_vlan_promisc, dsp,
299 299 &dsp->ds_vlan_mph, MAC_PROMISC_FLAGS_NO_PHYS);
300 300 }
301 301 } else if (dsp->ds_promisc == DLS_PROMISC_SAP && new_flags != 0 &&
302 302 new_flags != dsp->ds_promisc) {
303 303 /*
304 304 * If the old flag is PROMISC_SAP, but the current flag has
305 305 * changed to some new non-zero value, we need to turn the
306 306 * physical promiscuous mode.
307 307 */
308 308 ASSERT(dsp->ds_mph != NULL);
309 309 mac_promisc_remove(dsp->ds_mph);
310 310 /* Honors both after-remove and before-add semantics! */
311 311 dsp->ds_promisc = new_flags;
312 312 err = mac_promisc_add(dsp->ds_mch, mptype,
313 313 dls_rx_promisc, dsp, &dsp->ds_mph, 0);
314 314 if (err != 0)
315 315 dsp->ds_promisc = old_flags;
316 316 } else {
317 317 /* No adding or removing, but record the new flags anyway. */
318 318 dsp->ds_promisc = new_flags;
319 319 }
320 320
321 321 return (err);
322 322 }
323 323
324 324 int
325 325 dls_multicst_add(dld_str_t *dsp, const uint8_t *addr)
326 326 {
327 327 int err;
328 328 dls_multicst_addr_t **pp;
329 329 dls_multicst_addr_t *p;
330 330 uint_t addr_length;
331 331
332 332 ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
333 333
334 334 /*
335 335 * Check whether the address is in the list of enabled addresses for
336 336 * this dld_str_t.
337 337 */
338 338 addr_length = dsp->ds_mip->mi_addr_length;
339 339
340 340 /*
341 341 * Protect against concurrent access of ds_dmap by data threads using
342 342 * ds_rw_lock. The mac perimeter serializes the dls_multicst_add and
343 343 * remove operations. Dropping the ds_rw_lock across mac calls is thus
344 344 * ok and is also required by the locking protocol.
345 345 */
346 346 rw_enter(&dsp->ds_rw_lock, RW_WRITER);
347 347 for (pp = &(dsp->ds_dmap); (p = *pp) != NULL; pp = &(p->dma_nextp)) {
348 348 if (bcmp(addr, p->dma_addr, addr_length) == 0) {
349 349 /*
350 350 * It is there so there's nothing to do.
351 351 */
352 352 err = 0;
353 353 goto done;
354 354 }
355 355 }
356 356
357 357 /*
358 358 * Allocate a new list item and add it to the list.
359 359 */
360 360 p = kmem_zalloc(sizeof (dls_multicst_addr_t), KM_SLEEP);
361 361 bcopy(addr, p->dma_addr, addr_length);
362 362 *pp = p;
363 363 rw_exit(&dsp->ds_rw_lock);
364 364
365 365 /*
366 366 * Enable the address at the MAC.
367 367 */
368 368 err = mac_multicast_add(dsp->ds_mch, addr);
369 369 if (err == 0)
370 370 return (0);
371 371
372 372 /* Undo the operation as it has failed */
373 373 rw_enter(&dsp->ds_rw_lock, RW_WRITER);
374 374 ASSERT(*pp == p && p->dma_nextp == NULL);
375 375 *pp = NULL;
376 376 kmem_free(p, sizeof (dls_multicst_addr_t));
377 377 done:
378 378 rw_exit(&dsp->ds_rw_lock);
379 379 return (err);
380 380 }
381 381
382 382 int
383 383 dls_multicst_remove(dld_str_t *dsp, const uint8_t *addr)
384 384 {
385 385 dls_multicst_addr_t **pp;
386 386 dls_multicst_addr_t *p;
387 387 uint_t addr_length;
388 388
389 389 ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
390 390
391 391 /*
392 392 * Find the address in the list of enabled addresses for this
393 393 * dld_str_t.
394 394 */
395 395 addr_length = dsp->ds_mip->mi_addr_length;
396 396
397 397 /*
398 398 * Protect against concurrent access to ds_dmap by data threads using
399 399 * ds_rw_lock. The mac perimeter serializes the dls_multicst_add and
400 400 * remove operations. Dropping the ds_rw_lock across mac calls is thus
401 401 * ok and is also required by the locking protocol.
402 402 */
403 403 rw_enter(&dsp->ds_rw_lock, RW_WRITER);
404 404 for (pp = &(dsp->ds_dmap); (p = *pp) != NULL; pp = &(p->dma_nextp)) {
405 405 if (bcmp(addr, p->dma_addr, addr_length) == 0)
406 406 break;
407 407 }
408 408
409 409 /*
410 410 * If we walked to the end of the list then the given address is
411 411 * not currently enabled for this dld_str_t.
412 412 */
413 413 if (p == NULL) {
414 414 rw_exit(&dsp->ds_rw_lock);
415 415 return (ENOENT);
416 416 }
417 417
418 418 /*
419 419 * Remove the address from the list.
420 420 */
421 421 *pp = p->dma_nextp;
422 422 rw_exit(&dsp->ds_rw_lock);
423 423
424 424 /*
425 425 * Disable the address at the MAC.
426 426 */
427 427 mac_multicast_remove(dsp->ds_mch, addr);
428 428 kmem_free(p, sizeof (dls_multicst_addr_t));
429 429 return (0);
430 430 }
431 431
432 432 mblk_t *
433 433 dls_header(dld_str_t *dsp, const uint8_t *addr, uint16_t sap, uint_t pri,
434 434 mblk_t **payloadp)
435 435 {
436 436 uint16_t vid;
437 437 size_t extra_len;
438 438 uint16_t mac_sap;
439 439 mblk_t *mp, *payload;
440 440 boolean_t is_ethernet = (dsp->ds_mip->mi_media == DL_ETHER);
441 441 struct ether_vlan_header *evhp;
442 442
443 443 vid = mac_client_vid(dsp->ds_mch);
444 444 payload = (payloadp == NULL) ? NULL : (*payloadp);
445 445
446 446 /*
447 447 * In the case of Ethernet, we need to tell mac_header() if we need
448 448 * extra room beyond the Ethernet header for a VLAN header. We'll
449 449 * need to add a VLAN header if this isn't an ETHERTYPE_VLAN listener
450 450 * (because such streams will be handling VLAN headers on their own)
451 451 * and one of the following conditions is satisfied:
452 452 *
453 453 * - This is a VLAN stream
454 454 * - This is a physical stream, the priority is not 0, and user
455 455 * priority tagging is allowed.
456 456 */
457 457 if (is_ethernet && sap != ETHERTYPE_VLAN &&
458 458 (vid != VLAN_ID_NONE ||
459 459 (pri != 0 && dsp->ds_dlp->dl_tagmode != LINK_TAGMODE_VLANONLY))) {
460 460 extra_len = sizeof (struct ether_vlan_header) -
461 461 sizeof (struct ether_header);
462 462 mac_sap = ETHERTYPE_VLAN;
463 463 } else {
464 464 extra_len = 0;
465 465 mac_sap = sap;
466 466 }
467 467
468 468 mp = mac_header(dsp->ds_mh, addr, mac_sap, payload, extra_len);
469 469 if (mp == NULL)
470 470 return (NULL);
471 471
472 472 if ((vid == VLAN_ID_NONE && (pri == 0 ||
473 473 dsp->ds_dlp->dl_tagmode == LINK_TAGMODE_VLANONLY)) || !is_ethernet)
474 474 return (mp);
475 475
476 476 /*
477 477 * Fill in the tag information.
478 478 */
479 479 ASSERT(MBLKL(mp) == sizeof (struct ether_header));
480 480 if (extra_len != 0) {
481 481 mp->b_wptr += extra_len;
482 482 evhp = (struct ether_vlan_header *)mp->b_rptr;
483 483 evhp->ether_tci = htons(VLAN_TCI(pri, ETHER_CFI, vid));
484 484 evhp->ether_type = htons(sap);
485 485 } else {
486 486 /*
487 487 * The stream is ETHERTYPE_VLAN listener, so its VLAN tag is
488 488 * in the payload. Update the priority.
489 489 */
490 490 struct ether_vlan_extinfo *extinfo;
491 491 size_t len = sizeof (struct ether_vlan_extinfo);
492 492
493 493 ASSERT(sap == ETHERTYPE_VLAN);
494 494 ASSERT(payload != NULL);
495 495
496 496 if ((DB_REF(payload) > 1) || (MBLKL(payload) < len)) {
497 497 mblk_t *newmp;
498 498
499 499 /*
500 500 * Because some DLS consumers only check the db_ref
501 501 * count of the first mblk, we pullup 'payload' into
502 502 * a single mblk.
503 503 */
504 504 newmp = msgpullup(payload, -1);
505 505 if ((newmp == NULL) || (MBLKL(newmp) < len)) {
506 506 freemsg(newmp);
507 507 freemsg(mp);
508 508 return (NULL);
509 509 } else {
510 510 freemsg(payload);
511 511 *payloadp = payload = newmp;
512 512 }
513 513 }
514 514
515 515 extinfo = (struct ether_vlan_extinfo *)payload->b_rptr;
516 516 extinfo->ether_tci = htons(VLAN_TCI(pri, ETHER_CFI,
517 517 VLAN_ID(ntohs(extinfo->ether_tci))));
518 518 }
519 519 return (mp);
520 520 }
521 521
522 522 void
523 523 dls_rx_set(dld_str_t *dsp, dls_rx_t rx, void *arg)
524 524 {
525 525 mutex_enter(&dsp->ds_lock);
526 526 dsp->ds_rx = rx;
527 527 dsp->ds_rx_arg = arg;
528 528 mutex_exit(&dsp->ds_lock);
529 529 }
530 530
531 531 static boolean_t
532 532 dls_accept_common(dld_str_t *dsp, mac_header_info_t *mhip, dls_rx_t *ds_rx,
533 533 void **ds_rx_arg, boolean_t promisc, boolean_t promisc_loopback)
534 534 {
535 535 dls_multicst_addr_t *dmap;
536 536 size_t addr_length = dsp->ds_mip->mi_addr_length;
537 537
538 538 /*
539 539 * We must not accept packets if the dld_str_t is not marked as bound
540 540 * or is being removed.
541 541 */
542 542 if (dsp->ds_dlstate != DL_IDLE)
543 543 goto refuse;
544 544
545 545 if (dsp->ds_promisc != 0) {
546 546 /*
547 547 * Filter out packets that arrived from the data path
548 548 * (i_dls_link_rx) when promisc mode is on. We need to correlate
549 549 * the ds_promisc flags with the mac header destination type. If
550 550 * only DLS_PROMISC_MULTI is enabled, we need to only reject
551 551 * multicast packets as those are the only ones which filter up
552 552 * the promiscuous path. If we have DLS_PROMISC_PHYS or
553 553 * DLS_PROMISC_SAP set, then we know that we'll be seeing
554 554 * everything, so we should drop it now.
555 555 */
556 556 if (!promisc && !(dsp->ds_promisc == DLS_PROMISC_MULTI &&
557 557 mhip->mhi_dsttype != MAC_ADDRTYPE_MULTICAST))
558 558 goto refuse;
559 559 /*
560 560 * If the dls_impl_t is in 'all physical' mode then
561 561 * always accept.
562 562 */
563 563 if (dsp->ds_promisc & DLS_PROMISC_PHYS)
564 564 goto accept;
565 565
566 566 /*
567 567 * Loopback packets i.e. packets sent out by DLS on a given
568 568 * mac end point, will be accepted back by DLS on loopback
569 569 * from the mac, only in the 'all physical' mode which has been
570 570 * covered by the previous check above
571 571 */
572 572 if (promisc_loopback)
573 573 goto refuse;
574 574 }
575 575
576 576 switch (mhip->mhi_dsttype) {
577 577 case MAC_ADDRTYPE_UNICAST:
578 578 case MAC_ADDRTYPE_BROADCAST:
579 579 /*
580 580 * We can accept unicast and broadcast packets because
581 581 * filtering is already done by the mac layer.
582 582 */
583 583 goto accept;
584 584 case MAC_ADDRTYPE_MULTICAST:
585 585 /*
586 586 * Additional filtering is needed for multicast addresses
587 587 * because different streams may be interested in different
588 588 * addresses.
589 589 */
590 590 if (dsp->ds_promisc & DLS_PROMISC_MULTI)
591 591 goto accept;
592 592
593 593 rw_enter(&dsp->ds_rw_lock, RW_READER);
594 594 for (dmap = dsp->ds_dmap; dmap != NULL;
595 595 dmap = dmap->dma_nextp) {
596 596 if (memcmp(mhip->mhi_daddr, dmap->dma_addr,
597 597 addr_length) == 0) {
598 598 rw_exit(&dsp->ds_rw_lock);
599 599 goto accept;
600 600 }
601 601 }
602 602 rw_exit(&dsp->ds_rw_lock);
603 603 break;
604 604 }
605 605
606 606 refuse:
607 607 return (B_FALSE);
608 608
609 609 accept:
610 610 /*
611 611 * the returned ds_rx and ds_rx_arg will always be in sync.
612 612 */
613 613 mutex_enter(&dsp->ds_lock);
614 614 *ds_rx = dsp->ds_rx;
615 615 *ds_rx_arg = dsp->ds_rx_arg;
616 616 mutex_exit(&dsp->ds_lock);
617 617
618 618 return (B_TRUE);
619 619 }
620 620
621 621 /* ARGSUSED */
622 622 boolean_t
623 623 dls_accept(dld_str_t *dsp, mac_header_info_t *mhip, dls_rx_t *ds_rx,
624 624 void **ds_rx_arg)
625 625 {
626 626 return (dls_accept_common(dsp, mhip, ds_rx, ds_rx_arg, B_FALSE,
627 627 B_FALSE));
628 628 }
629 629
630 630 boolean_t
631 631 dls_accept_promisc(dld_str_t *dsp, mac_header_info_t *mhip, dls_rx_t *ds_rx,
632 632 void **ds_rx_arg, boolean_t loopback)
633 633 {
634 634 return (dls_accept_common(dsp, mhip, ds_rx, ds_rx_arg, B_TRUE,
635 635 loopback));
636 636 }
637 637
638 638 int
639 639 dls_mac_active_set(dls_link_t *dlp)
640 640 {
641 641 int err = 0;
642 642
643 643 /*
644 644 * First client; add the primary unicast address.
↓ open down ↓ |
451 lines elided |
↑ open up ↑ |
645 645 */
646 646 if (dlp->dl_nactive == 0) {
647 647 /*
648 648 * First client; add the primary unicast address.
649 649 */
650 650 mac_diag_t diag;
651 651
652 652 /* request the primary MAC address */
653 653 if ((err = mac_unicast_add(dlp->dl_mch, NULL,
654 654 MAC_UNICAST_PRIMARY | MAC_UNICAST_TAG_DISABLE |
655 - MAC_UNICAST_DISABLE_TX_VID_CHECK, &dlp->dl_mah, 0,
656 - &diag)) != 0) {
655 + MAC_UNICAST_DISABLE_TX_VID_CHECK, &dlp->dl_mah,
656 + VLAN_ID_NONE, &diag)) != 0) {
657 657 return (err);
658 658 }
659 659
660 660 /*
661 661 * Set the function to start receiving packets.
662 662 */
663 663 mac_rx_set(dlp->dl_mch, i_dls_link_rx, dlp);
664 664 }
665 665 dlp->dl_nactive++;
666 666 return (0);
667 667 }
668 668
669 669 void
670 670 dls_mac_active_clear(dls_link_t *dlp)
671 671 {
672 672 if (--dlp->dl_nactive == 0) {
673 673 ASSERT(dlp->dl_mah != NULL);
674 674 (void) mac_unicast_remove(dlp->dl_mch, dlp->dl_mah);
675 675 dlp->dl_mah = NULL;
676 676 mac_rx_clear(dlp->dl_mch);
677 677 }
678 678 }
679 679
680 680 int
681 681 dls_active_set(dld_str_t *dsp)
682 682 {
683 683 int err = 0;
684 684
685 685 ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
686 686
687 687 if (dsp->ds_passivestate == DLD_PASSIVE)
688 688 return (0);
689 689
690 690 /* If we're already active, then there's nothing more to do. */
691 691 if ((dsp->ds_nactive == 0) &&
692 692 ((err = dls_mac_active_set(dsp->ds_dlp)) != 0)) {
693 693 /* except for ENXIO all other errors are mapped to EBUSY */
694 694 if (err != ENXIO)
695 695 return (EBUSY);
696 696 return (err);
697 697 }
698 698
699 699 dsp->ds_passivestate = DLD_ACTIVE;
700 700 dsp->ds_nactive++;
701 701 return (0);
702 702 }
703 703
704 704 /*
705 705 * Note that dls_active_set() is called whenever an active operation
706 706 * (DL_BIND_REQ, DL_ENABMULTI_REQ ...) is processed and
707 707 * dls_active_clear(dsp, B_FALSE) is called whenever the active operation
708 708 * is being undone (DL_UNBIND_REQ, DL_DISABMULTI_REQ ...). In some cases,
709 709 * a stream is closed without every active operation being undone and we
710 710 * need to clear all the "active" states by calling
711 711 * dls_active_clear(dsp, B_TRUE).
712 712 */
713 713 void
714 714 dls_active_clear(dld_str_t *dsp, boolean_t all)
715 715 {
716 716 ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
717 717
718 718 if (dsp->ds_passivestate == DLD_PASSIVE)
719 719 return;
720 720
721 721 if (all && dsp->ds_nactive == 0)
722 722 return;
723 723
724 724 ASSERT(dsp->ds_nactive > 0);
725 725
726 726 dsp->ds_nactive -= (all ? dsp->ds_nactive : 1);
727 727 if (dsp->ds_nactive != 0)
728 728 return;
729 729
730 730 ASSERT(dsp->ds_passivestate == DLD_ACTIVE);
731 731 dls_mac_active_clear(dsp->ds_dlp);
732 732 dsp->ds_passivestate = DLD_UNINITIALIZED;
733 733 }
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX