net/eth: Always add VLAN tag
It is possible to have another VLAN tag even if the packet is already tagged. Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
parent
85427bf388
commit
aaa8a15c96
@ -40,7 +40,10 @@ struct NetTxPkt {
|
||||
|
||||
struct iovec *vec;
|
||||
|
||||
uint8_t l2_hdr[ETH_MAX_L2_HDR_LEN];
|
||||
struct {
|
||||
struct eth_header eth;
|
||||
struct vlan_header vlan[3];
|
||||
} l2_hdr;
|
||||
union {
|
||||
struct ip_header ip;
|
||||
struct ip6_header ip6;
|
||||
@ -365,18 +368,13 @@ bool net_tx_pkt_build_vheader(struct NetTxPkt *pkt, bool tso_enable,
|
||||
void net_tx_pkt_setup_vlan_header_ex(struct NetTxPkt *pkt,
|
||||
uint16_t vlan, uint16_t vlan_ethtype)
|
||||
{
|
||||
bool is_new;
|
||||
assert(pkt);
|
||||
|
||||
eth_setup_vlan_headers(pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_base,
|
||||
vlan, vlan_ethtype, &is_new);
|
||||
&pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_len,
|
||||
vlan, vlan_ethtype);
|
||||
|
||||
/* update l2hdrlen */
|
||||
if (is_new) {
|
||||
pkt->hdr_len += sizeof(struct vlan_header);
|
||||
pkt->vec[NET_TX_PKT_L2HDR_FRAG].iov_len +=
|
||||
sizeof(struct vlan_header);
|
||||
}
|
||||
pkt->hdr_len += sizeof(struct vlan_header);
|
||||
}
|
||||
|
||||
bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, void *base, size_t len)
|
||||
|
@ -353,8 +353,8 @@ eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
|
||||
uint16_t
|
||||
eth_get_l3_proto(const struct iovec *l2hdr_iov, int iovcnt, size_t l2hdr_len);
|
||||
|
||||
void eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag,
|
||||
uint16_t vlan_ethtype, bool *is_new);
|
||||
void eth_setup_vlan_headers(struct eth_header *ehdr, size_t *ehdr_size,
|
||||
uint16_t vlan_tag, uint16_t vlan_ethtype);
|
||||
|
||||
|
||||
uint8_t eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto);
|
||||
|
22
net/eth.c
22
net/eth.c
@ -21,26 +21,16 @@
|
||||
#include "net/checksum.h"
|
||||
#include "net/tap.h"
|
||||
|
||||
void eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag,
|
||||
uint16_t vlan_ethtype, bool *is_new)
|
||||
void eth_setup_vlan_headers(struct eth_header *ehdr, size_t *ehdr_size,
|
||||
uint16_t vlan_tag, uint16_t vlan_ethtype)
|
||||
{
|
||||
struct vlan_header *vhdr = PKT_GET_VLAN_HDR(ehdr);
|
||||
|
||||
switch (be16_to_cpu(ehdr->h_proto)) {
|
||||
case ETH_P_VLAN:
|
||||
case ETH_P_DVLAN:
|
||||
/* vlan hdr exists */
|
||||
*is_new = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* No VLAN header, put a new one */
|
||||
vhdr->h_proto = ehdr->h_proto;
|
||||
ehdr->h_proto = cpu_to_be16(vlan_ethtype);
|
||||
*is_new = true;
|
||||
break;
|
||||
}
|
||||
memmove(vhdr + 1, vhdr, *ehdr_size - ETH_HLEN);
|
||||
vhdr->h_tci = cpu_to_be16(vlan_tag);
|
||||
vhdr->h_proto = ehdr->h_proto;
|
||||
ehdr->h_proto = cpu_to_be16(vlan_ethtype);
|
||||
*ehdr_size += sizeof(*vhdr);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
|
Loading…
Reference in New Issue
Block a user