mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 03:29:43 +00:00
nvnet: Add unicast and multicast filtering
This commit is contained in:
parent
ccb1211cd6
commit
d6e5342f89
@ -25,6 +25,7 @@
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "net/net.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "nvnet_regs.h"
|
||||
@ -32,6 +33,8 @@
|
||||
#define IOPORT_SIZE 0x8
|
||||
#define MMIO_SIZE 0x400
|
||||
|
||||
static const uint8_t bcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
// #define DEBUG
|
||||
#ifdef DEBUG
|
||||
# define NVNET_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
|
||||
@ -432,6 +435,58 @@ static bool nvnet_is_packet_oversized(size_t size)
|
||||
return size > RX_ALLOC_BUFSIZE;
|
||||
}
|
||||
|
||||
static bool receive_filter(NvNetState *s, const uint8_t *buf, int size)
|
||||
{
|
||||
if (size < 6) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t rctl = nvnet_get_reg(s, NvRegPacketFilterFlags, 4);
|
||||
int isbcast = !memcmp(buf, bcast, sizeof bcast);
|
||||
|
||||
/* Broadcast */
|
||||
if (isbcast) {
|
||||
/* FIXME: bcast filtering */
|
||||
trace_nvnet_rx_filter_bcast_match();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(rctl & NVREG_PFF_MYADDR)) {
|
||||
/* FIXME: Confirm PFF_MYADDR filters mcast */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Multicast */
|
||||
uint32_t addr[2];
|
||||
addr[0] = cpu_to_le32(nvnet_get_reg(s, NvRegMulticastAddrA, 4));
|
||||
addr[1] = cpu_to_le32(nvnet_get_reg(s, NvRegMulticastAddrB, 4));
|
||||
if (memcmp(addr, bcast, sizeof bcast)) {
|
||||
uint32_t dest_addr[2];
|
||||
memcpy(dest_addr, buf, 6);
|
||||
dest_addr[0] &= cpu_to_le32(nvnet_get_reg(s, NvRegMulticastMaskA, 4));
|
||||
dest_addr[1] &= cpu_to_le32(nvnet_get_reg(s, NvRegMulticastMaskB, 4));
|
||||
|
||||
if (!memcmp(dest_addr, addr, 6)) {
|
||||
trace_nvnet_rx_filter_mcast_match(MAC_ARG(dest_addr));
|
||||
return true;
|
||||
} else {
|
||||
trace_nvnet_rx_filter_mcast_mismatch(MAC_ARG(dest_addr));
|
||||
}
|
||||
}
|
||||
|
||||
/* Unicast */
|
||||
addr[0] = cpu_to_le32(nvnet_get_reg(s, NvRegMacAddrA, 4));
|
||||
addr[1] = cpu_to_le32(nvnet_get_reg(s, NvRegMacAddrB, 4));
|
||||
if (!memcmp(buf, addr, 6)) {
|
||||
trace_nvnet_rx_filter_ucast_match(MAC_ARG(buf));
|
||||
return true;
|
||||
} else {
|
||||
trace_nvnet_rx_filter_ucast_mismatch(MAC_ARG(buf));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static ssize_t nvnet_receive_iov(NetClientState *nc,
|
||||
const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
@ -443,10 +498,17 @@ static ssize_t nvnet_receive_iov(NetClientState *nc,
|
||||
if (nvnet_is_packet_oversized(size)) {
|
||||
/* Drop */
|
||||
NVNET_DPRINTF("%s packet too large!\n", __func__);
|
||||
trace_nvnet_rx_oversized(size);
|
||||
return size;
|
||||
}
|
||||
|
||||
iov_to_buf(iov, iovcnt, 0, s->rx_dma_buf, size);
|
||||
|
||||
if (!receive_filter(s, s->rx_dma_buf, size)) {
|
||||
trace_nvnet_rx_filter_dropped();
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nvnet_hex_dump(s, s->rx_dma_buf, size);
|
||||
#endif
|
||||
|
@ -7,3 +7,10 @@ nvnet_reg_read(uint32_t addr, const char *name, unsigned int size, uint64_t val)
|
||||
nvnet_reg_write(uint32_t addr, const char *name, unsigned int size, uint64_t val) "addr 0x%"PRIx32" %s size %d val 0x%"PRIx64
|
||||
nvnet_io_read(uint32_t addr, unsigned int size, uint64_t val) "addr 0x%"PRIx32" size %d val 0x%"PRIx64
|
||||
nvnet_io_write(uint32_t addr, unsigned int size, uint64_t val) "addr 0x%"PRIx32" size %d val 0x%"PRIx64
|
||||
nvnet_rx_filter_bcast_match(void) "broadcast match"
|
||||
nvnet_rx_filter_mcast_match(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "multicast match: %02x:%02x:%02x:%02x:%02x:%02x"
|
||||
nvnet_rx_filter_mcast_mismatch(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "multicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x"
|
||||
nvnet_rx_filter_ucast_match(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) "unicast match: %02x:%02x:%02x:%02x:%02x:%02x"
|
||||
nvnet_rx_filter_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"
|
||||
nvnet_rx_oversized(size_t size) "Received packet dropped because it was oversized (%zu bytes)"
|
||||
nvnet_rx_filter_dropped(void) "Received packet dropped by RX filter"
|
||||
|
Loading…
Reference in New Issue
Block a user