Page MenuHomeFreeBSD

D26436.id77185.diff
No OneTemporary

D26436.id77185.diff

Index: sbin/ifconfig/ifconfig.8
===================================================================
--- sbin/ifconfig/ifconfig.8
+++ sbin/ifconfig/ifconfig.8
@@ -592,7 +592,7 @@
not on a
.Xr vlan 4
interface itself.
-.It Fl vlanmtu , vlanhwtag, vlanhwfilter, vlanhwtso
+.It Fl vlanmtu , vlanhwtag , vlanhwfilter , vlanhwtso
If the driver offers user-configurable VLAN support, disable
reception of extended frames, tag processing in hardware,
frame filtering in hardware, or TSO on VLAN,
@@ -2690,14 +2690,18 @@
.Pp
The following parameters are specific to
.Xr vlan 4
+and
+.Xr svlan 4
interfaces:
.Bl -tag -width indent
.It Cm vlan Ar vlan_tag
Set the VLAN tag value to
.Ar vlan_tag .
-This value is a 12-bit VLAN Identifier (VID) which is used to create an 802.1Q
-VLAN header for packets sent from the
+This value is a 12-bit VLAN Identifier (VID) which is used to create an
+802.1Q or 802.1ad VLAN header for packets sent from the
.Xr vlan 4
+or
+.Xr svlan 4
interface.
Note that
.Cm vlan
@@ -2732,29 +2736,48 @@
.Ar iface
with a
.Xr vlan 4
+or
+.Xr svlan 4
interface.
-Packets transmitted through the
+.Pp
+Packets transmitted through a
.Xr vlan 4
interface will be
diverted to the specified physical interface
.Ar iface
with 802.1Q VLAN encapsulation.
+Packets transmitted through a
+.Xr svlan 4
+interface will be
+diverted to the specified physical interface
+.Ar iface
+with 802.1ad VLAN encapsulation.
+.Pp
Packets with 802.1Q encapsulation received
by the parent interface with the correct VLAN Identifier will be diverted to
the associated
.Xr vlan 4
pseudo-interface.
-The
+Packets with 802.1ad encapsulation received
+by the parent interface with the correct VLAN Identifier will be diverted to
+the associated
+.Xr svlan 4
+pseudo-interface.
+.Pp
.Xr vlan 4
-interface is assigned a
+and
+.Xr svlan 4
+interfaces are assigned a
copy of the parent interface's flags and the parent's Ethernet address.
The
.Cm vlandev
and
.Cm vlan
must both be set at the same time.
-If the
+If a
.Xr vlan 4
+or
+.Xr svlan 4
interface already has
a physical interface associated with it, this command will fail.
To
@@ -2775,9 +2798,13 @@
.It Fl vlandev Op Ar iface
If the driver is a
.Xr vlan 4
+or
+.Xr svlan 4
pseudo device, disassociate the parent interface from it.
This breaks the link between the
.Xr vlan 4
+or
+.Xr svlan 4
interface and its parent,
clears its VLAN Identifier, flags and its link address and shuts the interface
down.
Index: sbin/ifconfig/ifvlan.c
===================================================================
--- sbin/ifconfig/ifvlan.c
+++ sbin/ifconfig/ifvlan.c
@@ -228,4 +228,5 @@
af_register(&af_vlan);
callback_register(vlan_cb, NULL);
clone_setdefcallback("vlan", vlan_create);
+ clone_setdefcallback("svlan", vlan_create);
}
Index: share/man/man4/Makefile
===================================================================
--- share/man/man4/Makefile
+++ share/man/man4/Makefile
@@ -739,7 +739,7 @@
MLINKS+=tun.4 if_tun.4
MLINKS+=ure.4 if_ure.4
MLINKS+=vge.4 if_vge.4
-MLINKS+=vlan.4 if_vlan.4
+MLINKS+=vlan.4 svlan.4 if_vlan.4 if_svlan.4
MLINKS+=vxlan.4 if_vxlan.4
MLINKS+=${_vmx.4} ${_if_vmx.4}
MLINKS+=vr.4 if_vr.4
Index: share/man/man4/vlan.4
===================================================================
--- share/man/man4/vlan.4
+++ share/man/man4/vlan.4
@@ -29,8 +29,9 @@
.Dt VLAN 4
.Os
.Sh NAME
-.Nm vlan
-.Nd "IEEE 802.1Q VLAN network interface"
+.Nm vlan ,
+.Nm svlan
+.Nd "IEEE 802.1Q/802.1ad VLAN network interfaces"
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following line in your
@@ -49,13 +50,17 @@
The
.Nm
driver demultiplexes frames tagged according to
-the IEEE 802.1Q standard into logical
+the IEEE 802.1Q and IEEE 802.1ad standards into logical
.Nm
-network interfaces, which allows routing/bridging between
-multiple VLANs through a single switch trunk port.
+and
+.Nm svlan
+network interfaces, respectively, allowing routing/bridging
+between multiple VLANs through a single switch trunk port.
.Pp
Each
-.Nm
+.Nm vlan
+or
+.Nm svlan
interface is created at runtime using interface cloning.
This is
most easily done with the
@@ -67,12 +72,16 @@
.Xr rc.conf 5 .
.Pp
To function, a
-.Nm
+.Nm vlan
+or
+.Nm svlan
interface must be assigned a parent interface and
numeric VLAN tag using
.Xr ifconfig 8 .
A single parent can be assigned to multiple
-.Nm
+.Nm vlan
+or
+.Nm svlan
interfaces provided they have different tags.
The parent interface is likely to be an Ethernet card connected
to a properly configured switch port.
@@ -152,10 +161,10 @@
However, some lack the capability
of transmitting and receiving long frames.
Assigning such an interface as the parent to
-.Nm
-will result in a reduced MTU on the corresponding
-.Nm
-interfaces.
+.Nm vlan
+or
+.Nm svlan
+will result in a reduced MTU on the child interfaces.
In the modern Internet, this is likely to cause
.Xr tcp 4
connectivity problems due to massive, inadequate
Index: sys/net/ethernet.h
===================================================================
--- sys/net/ethernet.h
+++ sys/net/ethernet.h
@@ -89,6 +89,15 @@
uint16_t evl_proto;
} __packed;
+/*
+ * 802.1q full tag.
+ */
+struct ether_8021q_tag {
+ uint16_t proto;
+ uint16_t vid;
+ uint8_t pcp;
+};
+
#define EVL_VLID_MASK 0x0FFF
#define EVL_PRI_MASK 0xE000
#define EVL_VLANOFTAG(tag) ((tag) & EVL_VLID_MASK)
@@ -441,11 +450,14 @@
extern char *ether_sprintf(const u_int8_t *);
void ether_vlan_mtap(struct bpf_if *, struct mbuf *,
void *, u_int);
-struct mbuf *ether_vlanencap(struct mbuf *, uint16_t);
-bool ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p,
- uint16_t vid, uint8_t pcp);
+struct mbuf *ether_vlanencap_proto(struct mbuf *, uint16_t, uint16_t);
+bool ether_8021q_frame(struct mbuf **mp, struct ifnet *ife,
+ struct ifnet *p, struct ether_8021q_tag *);
void ether_gen_addr(struct ifnet *ifp, struct ether_addr *hwaddr);
+static __inline struct mbuf *ether_vlanencap(struct mbuf *m, uint16_t tag)
+{ return ether_vlanencap_proto(m, tag, ETHERTYPE_VLAN); }
+
/* new ethernet interface attached event */
typedef void (*ether_ifattach_event_handler_t)(void *, struct ifnet *);
EVENTHANDLER_DECLARE(ether_ifattach_event, ether_ifattach_event_handler_t);
Index: sys/net/if_ethersubr.c
===================================================================
--- sys/net/if_ethersubr.c
+++ sys/net/if_ethersubr.c
@@ -441,11 +441,18 @@
static bool
ether_set_pcp(struct mbuf **mp, struct ifnet *ifp, uint8_t pcp)
{
+ struct ether_8021q_tag qtag;
struct ether_header *eh;
eh = mtod(*mp, struct ether_header *);
if (ntohs(eh->ether_type) == ETHERTYPE_VLAN ||
- ether_8021q_frame(mp, ifp, ifp, 0, pcp))
+ ntohs(eh->ether_type) == ETHERTYPE_QINQ)
+ return (true);
+
+ qtag.vid = 0;
+ qtag.pcp = pcp;
+ qtag.proto = ETHERTYPE_VLAN;
+ if (ether_8021q_frame(mp, ifp, ifp, &qtag))
return (true);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return (false);
@@ -618,7 +625,8 @@
* path correctly.
* TODO: Deal with Q-in-Q frames, but not arbitrary nesting levels.
*/
- if ((m->m_flags & M_VLANTAG) == 0 && etype == ETHERTYPE_VLAN) {
+ if ((m->m_flags & M_VLANTAG) == 0 &&
+ ((etype == ETHERTYPE_VLAN) || (etype == ETHERTYPE_QINQ))) {
struct ether_vlan_header *evl;
if (m->m_len < sizeof(*evl) &&
@@ -1303,7 +1311,7 @@
}
struct mbuf *
-ether_vlanencap(struct mbuf *m, uint16_t tag)
+ether_vlanencap_proto(struct mbuf *m, uint16_t tag, uint16_t proto)
{
struct ether_vlan_header *evl;
@@ -1325,7 +1333,7 @@
evl = mtod(m, struct ether_vlan_header *);
bcopy((char *)evl + ETHER_VLAN_ENCAP_LEN,
(char *)evl, ETHER_HDR_LEN - ETHER_TYPE_LEN);
- evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
+ evl->evl_encap_proto = htons(proto);
evl->evl_tag = htons(tag);
return (m);
}
@@ -1354,7 +1362,7 @@
bool
ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p,
- uint16_t vid, uint8_t pcp)
+ struct ether_8021q_tag *qtag)
{
struct m_tag *mtag;
int n;
@@ -1396,14 +1404,15 @@
*/
if (vlan_mtag_pcp && (mtag = m_tag_locate(*mp, MTAG_8021Q,
MTAG_8021Q_PCP_OUT, NULL)) != NULL)
- tag = EVL_MAKETAG(vid, *(uint8_t *)(mtag + 1), 0);
+ tag = EVL_MAKETAG(qtag->vid, *(uint8_t *)(mtag + 1), 0);
else
- tag = EVL_MAKETAG(vid, pcp, 0);
- if (p->if_capenable & IFCAP_VLAN_HWTAGGING) {
+ tag = EVL_MAKETAG(qtag->vid, qtag->pcp, 0);
+ if ((p->if_capenable & IFCAP_VLAN_HWTAGGING) &&
+ (qtag->proto == ETHERTYPE_VLAN)) {
(*mp)->m_pkthdr.ether_vtag = tag;
(*mp)->m_flags |= M_VLANTAG;
} else {
- *mp = ether_vlanencap(*mp, tag);
+ *mp = ether_vlanencap_proto(*mp, tag, qtag->proto);
if (*mp == NULL) {
if_printf(ife, "unable to prepend 802.1Q header");
return (false);
Index: sys/net/if_vlan.c
===================================================================
--- sys/net/if_vlan.c
+++ sys/net/if_vlan.c
@@ -17,7 +17,7 @@
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -185,17 +185,17 @@
struct ifvlantrunk *ifv_trunk;
struct ifnet *ifv_ifp;
#define TRUNK(ifv) ((ifv)->ifv_trunk)
-#define PARENT(ifv) ((ifv)->ifv_trunk->parent)
+#define PARENT(ifv) (TRUNK(ifv)->parent)
void *ifv_cookie;
int ifv_pflags; /* special flags we have set on parent */
int ifv_capenable;
int ifv_encaplen; /* encapsulation length */
int ifv_mtufudge; /* MTU fudged by this much */
int ifv_mintu; /* min transmission unit */
- uint16_t ifv_proto; /* encapsulation ethertype */
- uint16_t ifv_tag; /* tag to apply on packets leaving if */
- uint16_t ifv_vid; /* VLAN ID */
- uint8_t ifv_pcp; /* Priority Code Point (PCP). */
+ struct ether_8021q_tag ifv_qtag;
+#define ifv_proto ifv_qtag.proto
+#define ifv_vid ifv_qtag.vid
+#define ifv_pcp ifv_qtag.pcp
struct task lladdr_task;
CK_SLIST_HEAD(, vlan_mc_entry) vlan_mc_listhead;
#ifndef VLAN_ARRAY
@@ -216,15 +216,16 @@
extern int vlan_mtag_pcp;
static const char vlanname[] = "vlan";
+static const char svlanname[] = "svlan";
static MALLOC_DEFINE(M_VLAN, vlanname, "802.1Q Virtual LAN Interface");
static eventhandler_tag ifdetach_tag;
static eventhandler_tag iflladdr_tag;
/*
- * if_vlan uses two module-level synchronizations primitives to allow concurrent
- * modification of vlan interfaces and (mostly) allow for vlans to be destroyed
- * while they are being used for tx/rx. To accomplish this in a way that has
+ * if_vlan uses two module-level synchronizations primitives to allow concurrent
+ * modification of vlan interfaces and (mostly) allow for vlans to be destroyed
+ * while they are being used for tx/rx. To accomplish this in a way that has
* acceptable performance and cooperation with other parts of the network stack
* there is a non-sleepable epoch(9) and an sx(9).
*
@@ -244,7 +245,7 @@
static struct sx _VLAN_SX_ID;
#define VLAN_LOCKING_INIT() \
- sx_init(&_VLAN_SX_ID, "vlan_sx")
+ sx_init_flags(&_VLAN_SX_ID, "vlan_sx", SX_RECURSE)
#define VLAN_LOCKING_DESTROY() \
sx_destroy(&_VLAN_SX_ID)
@@ -306,13 +307,15 @@
const struct sockaddr *dst, struct route *ro);
static void vlan_unconfig(struct ifnet *ifp);
static void vlan_unconfig_locked(struct ifnet *ifp, int departing);
-static int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag);
+static int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag,
+ uint16_t proto);
static void vlan_link_state(struct ifnet *ifp);
static void vlan_capabilities(struct ifvlan *ifv);
static void vlan_trunk_capabilities(struct ifnet *ifp);
static struct ifnet *vlan_clone_match_ethervid(const char *, int *);
static int vlan_clone_match(struct if_clone *, const char *);
+static int svlan_clone_match(struct if_clone *, const char *);
static int vlan_clone_create(struct if_clone *, char *, size_t, caddr_t);
static int vlan_clone_destroy(struct if_clone *, struct ifnet *);
@@ -322,10 +325,13 @@
static void vlan_lladdr_fn(void *arg, int pending);
static struct if_clone *vlan_cloner;
+static struct if_clone *svlan_cloner;
#ifdef VIMAGE
VNET_DEFINE_STATIC(struct if_clone *, vlan_cloner);
#define V_vlan_cloner VNET(vlan_cloner)
+VNET_DEFINE_STATIC(struct if_clone *, svlan_cloner);
+#define V_svlan_cloner VNET(svlan_cloner)
#endif
static void
@@ -760,7 +766,7 @@
/*
* Return a driver specific cookie for this interface. Synchronization
- * with setcookie must be provided by the driver.
+ * with setcookie must be provided by the driver.
*/
static void *
vlan_cookie(struct ifnet *ifp)
@@ -810,16 +816,6 @@
return (ifp);
}
-/*
- * Recalculate the cached VLAN tag exposed via the MIB.
- */
-static void
-vlan_tag_recalculate(struct ifvlan *ifv)
-{
-
- ifv->ifv_tag = EVL_MAKETAG(ifv->ifv_vid, ifv->ifv_pcp, 0);
-}
-
/*
* VLAN support can be loaded as a module. The only place in the
* system that's intimately aware of this is ether_input. We hook
@@ -859,6 +855,8 @@
#ifndef VIMAGE
vlan_cloner = if_clone_advanced(vlanname, 0, vlan_clone_match,
vlan_clone_create, vlan_clone_destroy);
+ svlan_cloner = if_clone_advanced(svlanname, 0, svlan_clone_match,
+ vlan_clone_create, vlan_clone_destroy);
#endif
if (bootverbose)
printf("vlan: initialized, using "
@@ -867,11 +865,12 @@
#else
"hash tables with chaining"
#endif
-
+
"\n");
break;
case MOD_UNLOAD:
#ifndef VIMAGE
+ if_clone_detach(svlan_cloner);
if_clone_detach(vlan_cloner);
#endif
EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_tag);
@@ -911,6 +910,10 @@
vlan_cloner = if_clone_advanced(vlanname, 0, vlan_clone_match,
vlan_clone_create, vlan_clone_destroy);
V_vlan_cloner = vlan_cloner;
+
+ svlan_cloner = if_clone_advanced(svlanname, 0, svlan_clone_match,
+ vlan_clone_create, vlan_clone_destroy);
+ V_svlan_cloner = svlan_cloner;
}
VNET_SYSINIT(vnet_vlan_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
vnet_vlan_init, NULL);
@@ -918,7 +921,7 @@
static void
vnet_vlan_uninit(const void *unused __unused)
{
-
+ if_clone_detach(V_svlan_cloner);
if_clone_detach(V_vlan_cloner);
}
VNET_SYSUNINIT(vnet_vlan_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY,
@@ -926,7 +929,7 @@
#endif
/*
- * Check for <etherif>.<vlan> style interface names.
+ * Check for <etherif>.<vlan>[.<vlan> ...] style interface names.
*/
static struct ifnet *
vlan_clone_match_ethervid(const char *name, int *vidp)
@@ -937,7 +940,7 @@
int vid;
strlcpy(ifname, name, IFNAMSIZ);
- if ((cp = strchr(ifname, '.')) == NULL)
+ if ((cp = strrchr(ifname, '.')) == NULL)
return (NULL);
*cp = '\0';
if ((ifp = ifunit_ref(ifname)) == NULL)
@@ -982,6 +985,21 @@
return (1);
}
+static int
+svlan_clone_match(struct if_clone *ifc, const char *name)
+{
+ const char *cp;
+
+ if (strncmp(svlanname, name, strlen(svlanname)) != 0)
+ return (0);
+ for (cp = name + 5; *cp != '\0'; cp++) {
+ if (*cp < '0' || *cp > '9')
+ return (0);
+ }
+
+ return (1);
+}
+
static int
vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
{
@@ -990,6 +1008,7 @@
int unit;
int error;
int vid;
+ uint16_t proto;
struct ifvlan *ifv;
struct ifnet *ifp;
struct ifnet *p;
@@ -998,6 +1017,8 @@
struct vlanreq vlr;
static const u_char eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */
+ proto = ETHERTYPE_VLAN;
+
/*
* There are 3 (ugh) ways to specify the cloned device:
* o pass a parameter block with the clone request.
@@ -1024,8 +1045,10 @@
}
vid = vlr.vlr_tag;
wildcard = (unit < 0);
+ if (strncmp(svlanname, name, strlen(svlanname)) == 0)
+ proto = ETHERTYPE_QINQ;
} else if ((p = vlan_clone_match_ethervid(name, &vid)) != NULL) {
- unit = -1;
+ unit = vid;
wildcard = 0;
} else {
p = NULL;
@@ -1068,7 +1091,7 @@
* we don't conform to the default naming convention for interfaces.
*/
strlcpy(ifp->if_xname, name, IFNAMSIZ);
- ifp->if_dname = vlanname;
+ ifp->if_dname = (proto == ETHERTYPE_QINQ) ? svlanname : vlanname;
ifp->if_dunit = unit;
ifp->if_init = vlan_init;
@@ -1092,7 +1115,7 @@
sdl->sdl_type = IFT_L2VLAN;
if (p != NULL) {
- error = vlan_config(ifv, p, vid);
+ error = vlan_config(ifv, p, vid, proto);
if_rele(p);
if (error != 0) {
/*
@@ -1117,7 +1140,9 @@
vlan_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
{
struct ifvlan *ifv = ifp->if_softc;
- int unit = ifp->if_dunit;
+
+ if (ifp->if_vlantrunk)
+ return (EBUSY);
ether_ifdetach(ifp); /* first, remove it from system-wide lists */
vlan_unconfig(ifp); /* now it can be unconfigured and freed */
@@ -1130,7 +1155,7 @@
NET_EPOCH_WAIT();
if_free(ifp);
free(ifv, M_VLAN);
- ifc_free_unit(ifc, unit);
+ ifc_free_unit(ifc, ifp->if_dunit);
return (0);
}
@@ -1196,7 +1221,7 @@
return (ENETDOWN);
}
- if (!ether_8021q_frame(&m, ifp, p, ifv->ifv_vid, ifv->ifv_pcp)) {
+ if (!ether_8021q_frame(&m, ifp, p, &ifv->ifv_qtag)) {
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return (0);
}
@@ -1223,12 +1248,19 @@
NET_EPOCH_ASSERT();
+ /*
+ * Find the first non-VLAN parent interface.
+ */
ifv = ifp->if_softc;
- if (TRUNK(ifv) == NULL) {
- m_freem(m);
- return (ENETDOWN);
- }
- p = PARENT(ifv);
+ do {
+ if (TRUNK(ifv) == NULL) {
+ m_freem(m);
+ return (ENETDOWN);
+ }
+ p = PARENT(ifv);
+ ifv = p->if_softc;
+ } while (p->if_type == IFT_L2VLAN);
+
return p->if_output(ifp, m, dst, ro);
}
@@ -1357,7 +1389,8 @@
}
static int
-vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid)
+vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid,
+ uint16_t proto)
{
struct epoch_tracker et;
struct ifvlantrunk *trunk;
@@ -1369,6 +1402,7 @@
* they handle the tagging and headers themselves.
*/
if (p->if_type != IFT_ETHER &&
+ p->if_type != IFT_L2VLAN &&
(p->if_capenable & IFCAP_VLAN_HWTAGGING) == 0)
return (EPROTONOSUPPORT);
if ((p->if_flags & VLAN_IFFLAGS) != VLAN_IFFLAGS)
@@ -1400,11 +1434,10 @@
ifv->ifv_vid = vid; /* must set this before vlan_inshash() */
ifv->ifv_pcp = 0; /* Default: best effort delivery. */
- vlan_tag_recalculate(ifv);
error = vlan_inshash(trunk, ifv);
if (error)
goto done;
- ifv->ifv_proto = ETHERTYPE_VLAN;
+ ifv->ifv_proto = proto;
ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN;
ifv->ifv_mintu = ETHERMIN;
ifv->ifv_pflags = 0;
@@ -1915,7 +1948,7 @@
break;
}
oldmtu = ifp->if_mtu;
- error = vlan_config(ifv, p, vlr.vlr_tag);
+ error = vlan_config(ifv, p, vlr.vlr_tag, ifv->ifv_proto);
if_rele(p);
/*
@@ -1947,7 +1980,7 @@
VLAN_SUNLOCK();
error = copyout(&vlr, ifr_data_get_ptr(ifr), sizeof(vlr));
break;
-
+
case SIOCSIFFLAGS:
/*
* We should propagate selected flags to the parent,
@@ -2001,7 +2034,6 @@
}
ifv->ifv_pcp = ifr->ifr_vlan_pcp;
ifp->if_pcp = ifv->ifv_pcp;
- vlan_tag_recalculate(ifv);
/* broadcast event about PCP change */
EVENTHANDLER_INVOKE(ifnet_event, ifp, IFNET_EVENT_PCP);
break;

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 26, 4:23 PM (3 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17806668
Default Alt Text
D26436.id77185.diff (18 KB)

Event Timeline