e1000x: Share more Rx filtering logic
This saves some code and enables tracepoint for e1000's VLAN filtering. Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
parent
0b11783014
commit
e9e5b93069
@ -804,36 +804,11 @@ start_xmit(E1000State *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
receive_filter(E1000State *s, const uint8_t *buf, int size)
|
receive_filter(E1000State *s, const void *buf)
|
||||||
{
|
{
|
||||||
uint32_t rctl = s->mac_reg[RCTL];
|
return (!e1000x_is_vlan_packet(buf, s->mac_reg[VET]) ||
|
||||||
int isbcast = is_broadcast_ether_addr(buf);
|
e1000x_rx_vlan_filter(s->mac_reg, PKT_GET_VLAN_HDR(buf))) &&
|
||||||
int ismcast = is_multicast_ether_addr(buf);
|
e1000x_rx_group_filter(s->mac_reg, buf);
|
||||||
|
|
||||||
if (e1000x_is_vlan_packet(buf, le16_to_cpu(s->mac_reg[VET])) &&
|
|
||||||
e1000x_vlan_rx_filter_enabled(s->mac_reg)) {
|
|
||||||
uint16_t vid = lduw_be_p(&PKT_GET_VLAN_HDR(buf)->h_tci);
|
|
||||||
uint32_t vfta =
|
|
||||||
ldl_le_p((uint32_t *)(s->mac_reg + VFTA) +
|
|
||||||
((vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK));
|
|
||||||
if ((vfta & (1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK))) == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isbcast && !ismcast && (rctl & E1000_RCTL_UPE)) { /* promiscuous ucast */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ismcast && (rctl & E1000_RCTL_MPE)) { /* promiscuous mcast */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isbcast && (rctl & E1000_RCTL_BAM)) { /* broadcast enabled */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return e1000x_rx_group_filter(s->mac_reg, buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -949,7 +924,7 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!receive_filter(s, filter_buf, size)) {
|
if (!receive_filter(s, filter_buf)) {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,48 +1034,11 @@ e1000e_rx_l4_cso_enabled(E1000ECore *core)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
e1000e_receive_filter(E1000ECore *core, const uint8_t *buf, int size)
|
e1000e_receive_filter(E1000ECore *core, const void *buf)
|
||||||
{
|
{
|
||||||
uint32_t rctl = core->mac[RCTL];
|
return (!e1000x_is_vlan_packet(buf, core->mac[VET]) ||
|
||||||
|
e1000x_rx_vlan_filter(core->mac, PKT_GET_VLAN_HDR(buf))) &&
|
||||||
if (e1000x_is_vlan_packet(buf, core->mac[VET]) &&
|
e1000x_rx_group_filter(core->mac, buf);
|
||||||
e1000x_vlan_rx_filter_enabled(core->mac)) {
|
|
||||||
uint16_t vid = lduw_be_p(&PKT_GET_VLAN_HDR(buf)->h_tci);
|
|
||||||
uint32_t vfta =
|
|
||||||
ldl_le_p((uint32_t *)(core->mac + VFTA) +
|
|
||||||
((vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK));
|
|
||||||
if ((vfta & (1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK))) == 0) {
|
|
||||||
trace_e1000e_rx_flt_vlan_mismatch(vid);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
trace_e1000e_rx_flt_vlan_match(vid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (net_rx_pkt_get_packet_type(core->rx_pkt)) {
|
|
||||||
case ETH_PKT_UCAST:
|
|
||||||
if (rctl & E1000_RCTL_UPE) {
|
|
||||||
return true; /* promiscuous ucast */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ETH_PKT_BCAST:
|
|
||||||
if (rctl & E1000_RCTL_BAM) {
|
|
||||||
return true; /* broadcast enabled */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ETH_PKT_MCAST:
|
|
||||||
if (rctl & E1000_RCTL_MPE) {
|
|
||||||
return true; /* promiscuous mcast */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
return e1000x_rx_group_filter(core->mac, buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -1736,7 +1699,7 @@ e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt,
|
|||||||
net_rx_pkt_set_packet_type(core->rx_pkt,
|
net_rx_pkt_set_packet_type(core->rx_pkt,
|
||||||
get_eth_packet_type(PKT_GET_ETH_HDR(buf)));
|
get_eth_packet_type(PKT_GET_ETH_HDR(buf)));
|
||||||
|
|
||||||
if (!e1000e_receive_filter(core, buf, size)) {
|
if (!e1000e_receive_filter(core, buf)) {
|
||||||
trace_e1000e_rx_flt_dropped();
|
trace_e1000e_rx_flt_dropped();
|
||||||
return orig_size;
|
return orig_size;
|
||||||
}
|
}
|
||||||
|
@ -58,32 +58,64 @@ bool e1000x_is_vlan_packet(const void *buf, uint16_t vet)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool e1000x_rx_group_filter(uint32_t *mac, const uint8_t *buf)
|
bool e1000x_rx_vlan_filter(uint32_t *mac, const struct vlan_header *vhdr)
|
||||||
|
{
|
||||||
|
if (e1000x_vlan_rx_filter_enabled(mac)) {
|
||||||
|
uint16_t vid = lduw_be_p(&vhdr->h_tci);
|
||||||
|
uint32_t vfta =
|
||||||
|
ldl_le_p((uint32_t *)(mac + VFTA) +
|
||||||
|
((vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK));
|
||||||
|
if ((vfta & (1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK))) == 0) {
|
||||||
|
trace_e1000x_rx_flt_vlan_mismatch(vid);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_e1000x_rx_flt_vlan_match(vid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool e1000x_rx_group_filter(uint32_t *mac, const struct eth_header *ehdr)
|
||||||
{
|
{
|
||||||
static const int mta_shift[] = { 4, 3, 2, 0 };
|
static const int mta_shift[] = { 4, 3, 2, 0 };
|
||||||
uint32_t f, ra[2], *rp, rctl = mac[RCTL];
|
uint32_t f, ra[2], *rp, rctl = mac[RCTL];
|
||||||
|
|
||||||
|
if (is_broadcast_ether_addr(ehdr->h_dest)) {
|
||||||
|
if (rctl & E1000_RCTL_BAM) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (is_multicast_ether_addr(ehdr->h_dest)) {
|
||||||
|
if (rctl & E1000_RCTL_MPE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rctl & E1000_RCTL_UPE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (rp = mac + RA; rp < mac + RA + 32; rp += 2) {
|
for (rp = mac + RA; rp < mac + RA + 32; rp += 2) {
|
||||||
if (!(rp[1] & E1000_RAH_AV)) {
|
if (!(rp[1] & E1000_RAH_AV)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ra[0] = cpu_to_le32(rp[0]);
|
ra[0] = cpu_to_le32(rp[0]);
|
||||||
ra[1] = cpu_to_le32(rp[1]);
|
ra[1] = cpu_to_le32(rp[1]);
|
||||||
if (!memcmp(buf, (uint8_t *)ra, ETH_ALEN)) {
|
if (!memcmp(ehdr->h_dest, (uint8_t *)ra, ETH_ALEN)) {
|
||||||
trace_e1000x_rx_flt_ucast_match((int)(rp - mac - RA) / 2,
|
trace_e1000x_rx_flt_ucast_match((int)(rp - mac - RA) / 2,
|
||||||
MAC_ARG(buf));
|
MAC_ARG(ehdr->h_dest));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trace_e1000x_rx_flt_ucast_mismatch(MAC_ARG(buf));
|
trace_e1000x_rx_flt_ucast_mismatch(MAC_ARG(ehdr->h_dest));
|
||||||
|
|
||||||
f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];
|
f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];
|
||||||
f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff;
|
f = (((ehdr->h_dest[5] << 8) | ehdr->h_dest[4]) >> f) & 0xfff;
|
||||||
if (mac[MTA + (f >> 5)] & (1 << (f & 0x1f))) {
|
if (mac[MTA + (f >> 5)] & (1 << (f & 0x1f))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_e1000x_rx_flt_inexact_mismatch(MAC_ARG(buf),
|
trace_e1000x_rx_flt_inexact_mismatch(MAC_ARG(ehdr->h_dest),
|
||||||
(rctl >> E1000_RCTL_MO_SHIFT) & 3,
|
(rctl >> E1000_RCTL_MO_SHIFT) & 3,
|
||||||
f >> 5,
|
f >> 5,
|
||||||
mac[MTA + (f >> 5)]);
|
mac[MTA + (f >> 5)]);
|
||||||
|
@ -107,7 +107,9 @@ bool e1000x_rx_ready(PCIDevice *d, uint32_t *mac);
|
|||||||
|
|
||||||
bool e1000x_is_vlan_packet(const void *buf, uint16_t vet);
|
bool e1000x_is_vlan_packet(const void *buf, uint16_t vet);
|
||||||
|
|
||||||
bool e1000x_rx_group_filter(uint32_t *mac, const uint8_t *buf);
|
bool e1000x_rx_vlan_filter(uint32_t *mac, const struct vlan_header *vhdr);
|
||||||
|
|
||||||
|
bool e1000x_rx_group_filter(uint32_t *mac, const struct eth_header *ehdr);
|
||||||
|
|
||||||
bool e1000x_hw_rx_enabled(uint32_t *mac);
|
bool e1000x_hw_rx_enabled(uint32_t *mac);
|
||||||
|
|
||||||
|
@ -976,7 +976,6 @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header,
|
|||||||
uint16_t queues = 0;
|
uint16_t queues = 0;
|
||||||
uint16_t oversized = 0;
|
uint16_t oversized = 0;
|
||||||
uint16_t vid = be16_to_cpu(l2_header->vlan.h_tci) & VLAN_VID_MASK;
|
uint16_t vid = be16_to_cpu(l2_header->vlan.h_tci) & VLAN_VID_MASK;
|
||||||
bool accepted = false;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
memset(rss_info, 0, sizeof(E1000E_RSSInfo));
|
memset(rss_info, 0, sizeof(E1000E_RSSInfo));
|
||||||
@ -986,16 +985,8 @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (e1000x_is_vlan_packet(ehdr, core->mac[VET] & 0xffff) &&
|
if (e1000x_is_vlan_packet(ehdr, core->mac[VET] & 0xffff) &&
|
||||||
e1000x_vlan_rx_filter_enabled(core->mac)) {
|
!e1000x_rx_vlan_filter(core->mac, PKT_GET_VLAN_HDR(ehdr))) {
|
||||||
uint32_t vfta =
|
return queues;
|
||||||
ldl_le_p((uint32_t *)(core->mac + VFTA) +
|
|
||||||
((vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK));
|
|
||||||
if ((vfta & (1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK))) == 0) {
|
|
||||||
trace_e1000e_rx_flt_vlan_mismatch(vid);
|
|
||||||
return queues;
|
|
||||||
} else {
|
|
||||||
trace_e1000e_rx_flt_vlan_match(vid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core->mac[MRQC] & 1) {
|
if (core->mac[MRQC] & 1) {
|
||||||
@ -1103,33 +1094,7 @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (net_rx_pkt_get_packet_type(core->rx_pkt)) {
|
bool accepted = e1000x_rx_group_filter(core->mac, ehdr);
|
||||||
case ETH_PKT_UCAST:
|
|
||||||
if (rctl & E1000_RCTL_UPE) {
|
|
||||||
accepted = true; /* promiscuous ucast */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ETH_PKT_BCAST:
|
|
||||||
if (rctl & E1000_RCTL_BAM) {
|
|
||||||
accepted = true; /* broadcast enabled */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ETH_PKT_MCAST:
|
|
||||||
if (rctl & E1000_RCTL_MPE) {
|
|
||||||
accepted = true; /* promiscuous mcast */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!accepted) {
|
|
||||||
accepted = e1000x_rx_group_filter(core->mac, ehdr->h_dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
for (macp = core->mac + RA2; macp < core->mac + RA2 + 16; macp += 2) {
|
for (macp = core->mac + RA2; macp < core->mac + RA2 + 16; macp += 2) {
|
||||||
if (!(macp[1] & E1000_RAH_AV)) {
|
if (!(macp[1] & E1000_RAH_AV)) {
|
||||||
|
@ -106,6 +106,8 @@ e1000_receiver_overrun(size_t s, uint32_t rdh, uint32_t rdt) "Receiver overrun:
|
|||||||
# e1000x_common.c
|
# e1000x_common.c
|
||||||
e1000x_rx_can_recv_disabled(bool link_up, bool rx_enabled, bool pci_master) "link_up: %d, rx_enabled %d, pci_master %d"
|
e1000x_rx_can_recv_disabled(bool link_up, bool rx_enabled, bool pci_master) "link_up: %d, rx_enabled %d, pci_master %d"
|
||||||
e1000x_vlan_is_vlan_pkt(bool is_vlan_pkt, uint16_t eth_proto, uint16_t vet) "Is VLAN packet: %d, ETH proto: 0x%X, VET: 0x%X"
|
e1000x_vlan_is_vlan_pkt(bool is_vlan_pkt, uint16_t eth_proto, uint16_t vet) "Is VLAN packet: %d, ETH proto: 0x%X, VET: 0x%X"
|
||||||
|
e1000x_rx_flt_vlan_mismatch(uint16_t vid) "VID mismatch: 0x%X"
|
||||||
|
e1000x_rx_flt_vlan_match(uint16_t vid) "VID match: 0x%X"
|
||||||
e1000x_rx_flt_ucast_match(uint32_t idx, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x"
|
e1000x_rx_flt_ucast_match(uint32_t idx, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x"
|
||||||
e1000x_rx_flt_ucast_mismatch(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x"
|
e1000x_rx_flt_ucast_mismatch(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x"
|
||||||
e1000x_rx_flt_inexact_mismatch(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint32_t mo, uint32_t mta, uint32_t mta_val) "inexact mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] 0x%x"
|
e1000x_rx_flt_inexact_mismatch(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint32_t mo, uint32_t mta, uint32_t mta_val) "inexact mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] 0x%x"
|
||||||
@ -154,8 +156,6 @@ e1000e_rx_can_recv_rings_full(void) "Cannot receive: all rings are full"
|
|||||||
e1000e_rx_can_recv(void) "Can receive"
|
e1000e_rx_can_recv(void) "Can receive"
|
||||||
e1000e_rx_has_buffers(int ridx, uint32_t free_desc, size_t total_size, uint32_t desc_buf_size) "ring #%d: free descr: %u, packet size %zu, descr buffer size %u"
|
e1000e_rx_has_buffers(int ridx, uint32_t free_desc, size_t total_size, uint32_t desc_buf_size) "ring #%d: free descr: %u, packet size %zu, descr buffer size %u"
|
||||||
e1000e_rx_null_descriptor(void) "Null RX descriptor!!"
|
e1000e_rx_null_descriptor(void) "Null RX descriptor!!"
|
||||||
e1000e_rx_flt_vlan_mismatch(uint16_t vid) "VID mismatch: 0x%X"
|
|
||||||
e1000e_rx_flt_vlan_match(uint16_t vid) "VID match: 0x%X"
|
|
||||||
e1000e_rx_desc_ps_read(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) "buffers: [0x%"PRIx64", 0x%"PRIx64", 0x%"PRIx64", 0x%"PRIx64"]"
|
e1000e_rx_desc_ps_read(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) "buffers: [0x%"PRIx64", 0x%"PRIx64", 0x%"PRIx64", 0x%"PRIx64"]"
|
||||||
e1000e_rx_desc_ps_write(uint16_t a0, uint16_t a1, uint16_t a2, uint16_t a3) "bytes written: [%u, %u, %u, %u]"
|
e1000e_rx_desc_ps_write(uint16_t a0, uint16_t a1, uint16_t a2, uint16_t a3) "bytes written: [%u, %u, %u, %u]"
|
||||||
e1000e_rx_desc_buff_sizes(uint32_t b0, uint32_t b1, uint32_t b2, uint32_t b3) "buffer sizes: [%u, %u, %u, %u]"
|
e1000e_rx_desc_buff_sizes(uint32_t b0, uint32_t b1, uint32_t b2, uint32_t b3) "buffer sizes: [%u, %u, %u, %u]"
|
||||||
|
Loading…
Reference in New Issue
Block a user