| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_vlan.c,v 1.159 2021/07/14 06:50:22 yamaguchi Exp $ */ | | 1 | /* $NetBSD: if_vlan.c,v 1.160 2021/07/15 04:05:47 yamaguchi Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Andrew Doran, and by Jason R. Thorpe of Zembu Labs, Inc. | | 8 | * by Andrew Doran, and by Jason R. Thorpe of Zembu Labs, Inc. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -68,27 +68,27 @@ | | | @@ -68,27 +68,27 @@ |
68 | * enough of an Ethernet implementation to make ARP work. The way we do | | 68 | * enough of an Ethernet implementation to make ARP work. The way we do |
69 | * this is by telling everyone that we are an Ethernet interface, and then | | 69 | * this is by telling everyone that we are an Ethernet interface, and then |
70 | * catch the packets that ether_output() left on our output queue when it | | 70 | * catch the packets that ether_output() left on our output queue when it |
71 | * calls if_start(), rewrite them for use by the real outgoing interface, | | 71 | * calls if_start(), rewrite them for use by the real outgoing interface, |
72 | * and ask it to send them. | | 72 | * and ask it to send them. |
73 | * | | 73 | * |
74 | * TODO: | | 74 | * TODO: |
75 | * | | 75 | * |
76 | * - Need some way to notify vlan interfaces when the parent | | 76 | * - Need some way to notify vlan interfaces when the parent |
77 | * interface changes MTU. | | 77 | * interface changes MTU. |
78 | */ | | 78 | */ |
79 | | | 79 | |
80 | #include <sys/cdefs.h> | | 80 | #include <sys/cdefs.h> |
81 | __KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.159 2021/07/14 06:50:22 yamaguchi Exp $"); | | 81 | __KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.160 2021/07/15 04:05:47 yamaguchi Exp $"); |
82 | | | 82 | |
83 | #ifdef _KERNEL_OPT | | 83 | #ifdef _KERNEL_OPT |
84 | #include "opt_inet.h" | | 84 | #include "opt_inet.h" |
85 | #include "opt_net_mpsafe.h" | | 85 | #include "opt_net_mpsafe.h" |
86 | #endif | | 86 | #endif |
87 | | | 87 | |
88 | #include <sys/param.h> | | 88 | #include <sys/param.h> |
89 | #include <sys/systm.h> | | 89 | #include <sys/systm.h> |
90 | #include <sys/kernel.h> | | 90 | #include <sys/kernel.h> |
91 | #include <sys/mbuf.h> | | 91 | #include <sys/mbuf.h> |
92 | #include <sys/queue.h> | | 92 | #include <sys/queue.h> |
93 | #include <sys/socket.h> | | 93 | #include <sys/socket.h> |
94 | #include <sys/sockio.h> | | 94 | #include <sys/sockio.h> |
| @@ -1311,47 +1311,63 @@ vlan_ether_purgemulti(struct ifvlan *ifv | | | @@ -1311,47 +1311,63 @@ vlan_ether_purgemulti(struct ifvlan *ifv |
1311 | free(mc, M_DEVBUF); | | 1311 | free(mc, M_DEVBUF); |
1312 | } | | 1312 | } |
1313 | } | | 1313 | } |
1314 | | | 1314 | |
1315 | static void | | 1315 | static void |
1316 | vlan_start(struct ifnet *ifp) | | 1316 | vlan_start(struct ifnet *ifp) |
1317 | { | | 1317 | { |
1318 | struct ifvlan *ifv = ifp->if_softc; | | 1318 | struct ifvlan *ifv = ifp->if_softc; |
1319 | struct ifnet *p; | | 1319 | struct ifnet *p; |
1320 | struct ethercom *ec; | | 1320 | struct ethercom *ec; |
1321 | struct mbuf *m; | | 1321 | struct mbuf *m; |
1322 | struct ifvlan_linkmib *mib; | | 1322 | struct ifvlan_linkmib *mib; |
1323 | struct psref psref; | | 1323 | struct psref psref; |
| | | 1324 | struct ether_header *eh; |
1324 | int error; | | 1325 | int error; |
1325 | | | 1326 | |
1326 | mib = vlan_getref_linkmib(ifv, &psref); | | 1327 | mib = vlan_getref_linkmib(ifv, &psref); |
1327 | if (mib == NULL) | | 1328 | if (mib == NULL) |
1328 | return; | | 1329 | return; |
1329 | | | 1330 | |
1330 | if (__predict_false(mib->ifvm_p == NULL)) { | | 1331 | if (__predict_false(mib->ifvm_p == NULL)) { |
1331 | vlan_putref_linkmib(mib, &psref); | | 1332 | vlan_putref_linkmib(mib, &psref); |
1332 | return; | | 1333 | return; |
1333 | } | | 1334 | } |
1334 | | | 1335 | |
1335 | p = mib->ifvm_p; | | 1336 | p = mib->ifvm_p; |
1336 | ec = (void *)mib->ifvm_p; | | 1337 | ec = (void *)mib->ifvm_p; |
1337 | | | 1338 | |
1338 | ifp->if_flags |= IFF_OACTIVE; | | 1339 | ifp->if_flags |= IFF_OACTIVE; |
1339 | | | 1340 | |
1340 | for (;;) { | | 1341 | for (;;) { |
1341 | IFQ_DEQUEUE(&ifp->if_snd, m); | | 1342 | IFQ_DEQUEUE(&ifp->if_snd, m); |
1342 | if (m == NULL) | | 1343 | if (m == NULL) |
1343 | break; | | 1344 | break; |
1344 | | | 1345 | |
| | | 1346 | if (m->m_len < sizeof(*eh)) { |
| | | 1347 | m = m_pullup(m, sizeof(*eh)); |
| | | 1348 | if (m == NULL) { |
| | | 1349 | if_statinc(ifp, if_oerrors); |
| | | 1350 | continue; |
| | | 1351 | } |
| | | 1352 | } |
| | | 1353 | |
| | | 1354 | eh = mtod(m, struct ether_header *); |
| | | 1355 | if (ntohs(eh->ether_type) == ETHERTYPE_VLAN) { |
| | | 1356 | m_freem(m); |
| | | 1357 | if_statinc(ifp, if_noproto); |
| | | 1358 | continue; |
| | | 1359 | } |
| | | 1360 | |
1345 | #ifdef ALTQ | | 1361 | #ifdef ALTQ |
1346 | /* | | 1362 | /* |
1347 | * KERNEL_LOCK is required for ALTQ even if NET_MPSAFE is | | 1363 | * KERNEL_LOCK is required for ALTQ even if NET_MPSAFE is |
1348 | * defined. | | 1364 | * defined. |
1349 | */ | | 1365 | */ |
1350 | KERNEL_LOCK(1, NULL); | | 1366 | KERNEL_LOCK(1, NULL); |
1351 | /* | | 1367 | /* |
1352 | * If ALTQ is enabled on the parent interface, do | | 1368 | * If ALTQ is enabled on the parent interface, do |
1353 | * classification; the queueing discipline might | | 1369 | * classification; the queueing discipline might |
1354 | * not require classification, but might require | | 1370 | * not require classification, but might require |
1355 | * the address family/header pointer in the pktattr. | | 1371 | * the address family/header pointer in the pktattr. |
1356 | */ | | 1372 | */ |
1357 | if (ALTQ_IS_ENABLED(&p->if_snd)) { | | 1373 | if (ALTQ_IS_ENABLED(&p->if_snd)) { |
| @@ -1455,30 +1471,46 @@ vlan_start(struct ifnet *ifp) | | | @@ -1455,30 +1471,46 @@ vlan_start(struct ifnet *ifp) |
1455 | | | 1471 | |
1456 | /* Remove reference to mib before release */ | | 1472 | /* Remove reference to mib before release */ |
1457 | vlan_putref_linkmib(mib, &psref); | | 1473 | vlan_putref_linkmib(mib, &psref); |
1458 | } | | 1474 | } |
1459 | | | 1475 | |
1460 | static int | | 1476 | static int |
1461 | vlan_transmit(struct ifnet *ifp, struct mbuf *m) | | 1477 | vlan_transmit(struct ifnet *ifp, struct mbuf *m) |
1462 | { | | 1478 | { |
1463 | struct ifvlan *ifv = ifp->if_softc; | | 1479 | struct ifvlan *ifv = ifp->if_softc; |
1464 | struct ifnet *p; | | 1480 | struct ifnet *p; |
1465 | struct ethercom *ec; | | 1481 | struct ethercom *ec; |
1466 | struct ifvlan_linkmib *mib; | | 1482 | struct ifvlan_linkmib *mib; |
1467 | struct psref psref; | | 1483 | struct psref psref; |
| | | 1484 | struct ether_header *eh; |
1468 | int error; | | 1485 | int error; |
1469 | size_t pktlen = m->m_pkthdr.len; | | 1486 | size_t pktlen = m->m_pkthdr.len; |
1470 | bool mcast = (m->m_flags & M_MCAST) != 0; | | 1487 | bool mcast = (m->m_flags & M_MCAST) != 0; |
1471 | | | 1488 | |
| | | 1489 | if (m->m_len < sizeof(*eh)) { |
| | | 1490 | m = m_pullup(m, sizeof(*eh)); |
| | | 1491 | if (m == NULL) { |
| | | 1492 | if_statinc(ifp, if_oerrors); |
| | | 1493 | return ENOBUFS; |
| | | 1494 | } |
| | | 1495 | } |
| | | 1496 | |
| | | 1497 | eh = mtod(m, struct ether_header *); |
| | | 1498 | if (ntohs(eh->ether_type) == ETHERTYPE_VLAN) { |
| | | 1499 | m_freem(m); |
| | | 1500 | if_statinc(ifp, if_noproto); |
| | | 1501 | return EPROTONOSUPPORT; |
| | | 1502 | } |
| | | 1503 | |
1472 | mib = vlan_getref_linkmib(ifv, &psref); | | 1504 | mib = vlan_getref_linkmib(ifv, &psref); |
1473 | if (mib == NULL) { | | 1505 | if (mib == NULL) { |
1474 | m_freem(m); | | 1506 | m_freem(m); |
1475 | return ENETDOWN; | | 1507 | return ENETDOWN; |
1476 | } | | 1508 | } |
1477 | | | 1509 | |
1478 | if (__predict_false(mib->ifvm_p == NULL)) { | | 1510 | if (__predict_false(mib->ifvm_p == NULL)) { |
1479 | vlan_putref_linkmib(mib, &psref); | | 1511 | vlan_putref_linkmib(mib, &psref); |
1480 | m_freem(m); | | 1512 | m_freem(m); |
1481 | return ENETDOWN; | | 1513 | return ENETDOWN; |
1482 | } | | 1514 | } |
1483 | | | 1515 | |
1484 | p = mib->ifvm_p; | | 1516 | p = mib->ifvm_p; |