- bpf_packet_func bpf_func;
- struct ether_vlan_header * evl;
- int encaplen;
- ifvlan_ref ifv;
- struct ifnet * p;
- int soft_vlan;
- u_short tag;
- vlan_parent_ref vlp = NULL;
- int err;
- struct flowadv adv = { FADV_SUCCESS };
-
- if (m == 0) {
- return (0);
- }
- if ((m->m_flags & M_PKTHDR) == 0) {
- m_freem_list(m);
- return (0);
- }
- vlan_lock();
- ifv = ifnet_get_ifvlan_retained(ifp);
- if (ifv == NULL || ifvlan_flags_ready(ifv) == 0) {
- goto unlock_done;
- }
- vlp = ifvlan_get_vlan_parent_retained(ifv);
- if (vlp == NULL) {
- goto unlock_done;
- }
- p = vlp->vlp_ifp;
- (void)ifnet_stat_increment_out(ifp, 1, m->m_pkthdr.len, 0);
- soft_vlan = (ifnet_offload(p) & IF_HWASSIST_VLAN_TAGGING) == 0;
- bpf_func = ifv->ifv_bpf_output;
- tag = ifv->ifv_tag;
- encaplen = ifv->ifv_encaplen;
- vlan_unlock();
-
- ifvlan_release(ifv);
- vlan_parent_release(vlp);
-
- vlan_bpf_output(ifp, m, bpf_func);
-
- /* do not run parent's if_output() if the parent is not up */
- if ((ifnet_flags(p) & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) {
- m_freem(m);
- atomic_add_64(&ifp->if_collisions, 1);
- return (0);
- }
- /*
- * If underlying interface can do VLAN tag insertion itself,
- * just pass the packet along. However, we need some way to
- * tell the interface where the packet came from so that it
- * knows how to find the VLAN tag to use. We use a field in
- * the mbuf header to store the VLAN tag, and a bit in the
- * csum_flags field to mark the field as valid.
- */
- if (soft_vlan == 0) {
- m->m_pkthdr.csum_flags |= CSUM_VLAN_TAG_VALID;
- m->m_pkthdr.vlan_tag = tag;
- } else {
- M_PREPEND(m, encaplen, M_DONTWAIT);
- if (m == NULL) {
- printf("%s%d: unable to prepend VLAN header\n", ifnet_name(ifp),
- ifnet_unit(ifp));
- atomic_add_64(&ifp->if_oerrors, 1);
- return (0);
- }
- /* M_PREPEND takes care of m_len, m_pkthdr.len for us */
- if (m->m_len < (int)sizeof(*evl)) {
- m = m_pullup(m, sizeof(*evl));
- if (m == NULL) {
- printf("%s%d: unable to pullup VLAN header\n", ifnet_name(ifp),
- ifnet_unit(ifp));
- atomic_add_64(&ifp->if_oerrors, 1);
- return (0);
- }
- }
-
+ struct ether_vlan_header * evl;
+ int encaplen;
+ ifvlan_ref ifv;
+ struct ifnet * p;
+ int soft_vlan;
+ u_short tag;
+ vlan_parent_ref vlp = NULL;
+ int err;
+ struct flowadv adv = { .code = FADV_SUCCESS };
+
+ if (m == 0) {
+ return 0;
+ }
+ if ((m->m_flags & M_PKTHDR) == 0) {
+ m_freem_list(m);
+ return 0;
+ }
+ vlan_lock();
+ ifv = ifnet_get_ifvlan_retained(ifp);
+ if (ifv == NULL || ifvlan_flags_ready(ifv) == 0) {
+ goto unlock_done;
+ }
+ vlp = ifvlan_get_vlan_parent_retained(ifv);
+ if (vlp == NULL) {
+ goto unlock_done;
+ }
+ p = vlp->vlp_ifp;
+ (void)ifnet_stat_increment_out(ifp, 1, m->m_pkthdr.len, 0);
+ soft_vlan = (ifnet_offload(p) & IF_HWASSIST_VLAN_TAGGING) == 0;
+ tag = ifv->ifv_tag;
+ encaplen = ifv->ifv_encaplen;
+ vlan_unlock();
+
+ ifvlan_release(ifv);
+ vlan_parent_release(vlp);
+
+ bpf_tap_out(ifp, DLT_EN10MB, m, NULL, 0);
+
+ /* do not run parent's if_output() if the parent is not up */
+ if ((ifnet_flags(p) & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) {
+ m_freem(m);
+ atomic_add_64(&ifp->if_collisions, 1);
+ return 0;
+ }