Thu Jul 15 04:05:47 2021 UTC ()
vlan: drop tagged outgoing packets

vlan(4) doesn't support Q-in-Q yet.


(yamaguchi)
diff -r1.159 -r1.160 src/sys/net/if_vlan.c

cvs diff -r1.159 -r1.160 src/sys/net/if_vlan.c (expand / switch to unified diff)

--- src/sys/net/if_vlan.c 2021/07/14 06:50:22 1.159
+++ src/sys/net/if_vlan.c 2021/07/15 04:05:47 1.160
@@ -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
1315static void 1315static void
1316vlan_start(struct ifnet *ifp) 1316vlan_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
1460static int 1476static int
1461vlan_transmit(struct ifnet *ifp, struct mbuf *m) 1477vlan_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;