PDP11, VAX, ETHER: Generalize XQ device address filtering

Add optional enabling of broadcast address to hash based filter model.
LANCE based devices which use its AUTODIN II based hash generally
match the broadcast address independent of the contents of the
multicast hash.

This change to XQ mostly undoes the prior change to pdp11_xq and
brings the functionality into sim_ether so that it is generally available
for future ethernet devices.
This commit is contained in:
Mark Pizzolato 2021-12-14 11:39:18 -08:00
parent 40d4609385
commit 8b33921c92
4 changed files with 53 additions and 14 deletions

View file

@ -742,11 +742,15 @@ t_stat xq_show_filters (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
{ {
CTLR* xq = xq_unit2ctlr(uptr); CTLR* xq = xq_unit2ctlr(uptr);
char buffer[20]; char buffer[20];
size_t i; int i;
if (xq->var->mode == XQ_T_DELQA_PLUS) { if (xq->var->mode == XQ_T_DELQA_PLUS) {
eth_mac_fmt(&xq->var->init.phys, buffer); eth_mac_fmt(&xq->var->init.phys, buffer);
fprintf(st, "Physical Address=%s\n", buffer); fprintf(st, "Physical Address=%s\n", buffer);
for (i=1; i<xq->var->etherface->addr_count; i++) {
eth_mac_fmt((ETH_MAC*)xq->var->etherface->filter_address[i], buffer);
fprintf(st, "Additional Filter:[%2d]: %s\n", (int)i, buffer);
}
if (xq->var->etherface->hash_filter) { if (xq->var->etherface->hash_filter) {
fprintf(st, "Multicast Hash: "); fprintf(st, "Multicast Hash: ");
for (i=0; i<sizeof(xq->var->etherface->hash); ++i) for (i=0; i<sizeof(xq->var->etherface->hash); ++i)
@ -2403,9 +2407,7 @@ t_stat xq_wr_srqr_action(CTLR* xq)
xq->var->sanity.quarter_secs = 4*xq->var->init.hit_timeout; xq->var->sanity.quarter_secs = 4*xq->var->init.hit_timeout;
} }
xq->var->icr = xq->var->init.options & XQ_IN_OP_INT; xq->var->icr = xq->var->init.options & XQ_IN_OP_INT;
memcpy (&xq->var->turbo_macs[0], &xq->var->init.phys, sizeof (xq->var->turbo_macs[0])); status = eth_filter_hash_ex (xq->var->etherface, 1, &xq->var->init.phys, 0, xq->var->init.mode & XQ_IN_MO_PRO, TRUE, &xq->var->init.hash_filter);
memset (&xq->var->turbo_macs[1], 0xFF, sizeof (xq->var->turbo_macs[1])); /* LANCE explicitly also matches the broadcast address */
status = eth_filter_hash (xq->var->etherface, 2, xq->var->turbo_macs, 0, xq->var->init.mode & XQ_IN_MO_PRO, &xq->var->init.hash_filter);
xq->dev->dctrl = saved_debug; /* restore original debugging */ xq->dev->dctrl = saved_debug; /* restore original debugging */
} }
/* start the read service timer or enable asynch reading as appropriate */ /* start the read service timer or enable asynch reading as appropriate */
@ -2927,9 +2929,7 @@ t_stat xq_attach(UNIT* uptr, CONST char* cptr)
} }
if (xq->var->mode == XQ_T_DELQA_PLUS) { if (xq->var->mode == XQ_T_DELQA_PLUS) {
memcpy (&xq->var->turbo_macs[0], &xq->var->init.phys, sizeof (xq->var->turbo_macs[0])); eth_filter_hash_ex (xq->var->etherface, 1, &xq->var->init.phys, 0, xq->var->init.mode & XQ_IN_MO_PRO, TRUE, &xq->var->init.hash_filter);
memset (&xq->var->turbo_macs[1], 0xFF, sizeof (xq->var->turbo_macs[1])); /* LANCE explicitly also matches the broadcast address */
eth_filter_hash (xq->var->etherface, 2, xq->var->turbo_macs, 0, xq->var->init.mode & XQ_IN_MO_PRO, &xq->var->init.hash_filter);
} }
else else
if (xq->var->setup.valid) { if (xq->var->setup.valid) {

View file

@ -285,7 +285,6 @@ struct xq_device {
uint16 pending_interrupt; /* Pending Interrupt - DELQA-T only */ uint16 pending_interrupt; /* Pending Interrupt - DELQA-T only */
struct xq_turbo_init_block struct xq_turbo_init_block
init; init;
ETH_MAC turbo_macs[2]; /* Hardware MAC address + broadcast */
struct transmit_buffer_descriptor struct transmit_buffer_descriptor
xring[XQ_TURBO_XM_BCNT]; /* Transmit Buffer Ring */ xring[XQ_TURBO_XM_BCNT]; /* Transmit Buffer Ring */
uint32 tbindx; /* Transmit Buffer Ring Index */ uint32 tbindx; /* Transmit Buffer Ring Index */

View file

@ -4014,15 +4014,24 @@ return SCPE_OK;
t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses, t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
ETH_BOOL all_multicast, ETH_BOOL promiscuous) ETH_BOOL all_multicast, ETH_BOOL promiscuous)
{ {
return eth_filter_hash(dev, addr_count, addresses, return eth_filter_hash_ex(dev, addr_count, addresses,
all_multicast, promiscuous, all_multicast, promiscuous, FALSE,
NULL); NULL);
} }
t_stat eth_filter_hash(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses, t_stat eth_filter_hash(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
ETH_BOOL all_multicast, ETH_BOOL promiscuous, ETH_BOOL all_multicast, ETH_BOOL promiscuous,
ETH_MULTIHASH* const hash) ETH_MULTIHASH* const hash)
{ {
return eth_filter_hash_ex(dev, addr_count, addresses,
all_multicast, promiscuous, TRUE,
hash);
}
t_stat eth_filter_hash_ex(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
ETH_BOOL match_broadcast, ETH_MULTIHASH* const hash)
{
int i; int i;
char buf[116+66*ETH_FILTER_MAX]; char buf[116+66*ETH_FILTER_MAX];
char mac[20]; char mac[20];
@ -4035,7 +4044,7 @@ struct bpf_program bpf;
if (!dev) return SCPE_UNATT; if (!dev) return SCPE_UNATT;
/* filter count OK? */ /* filter count OK? */
if ((addr_count < 0) || (addr_count > ETH_FILTER_MAX)) if ((addr_count < 0) || ((addr_count + (match_broadcast ? 1 : 0)) > ETH_FILTER_MAX))
return SCPE_ARG; return SCPE_ARG;
else else
if (!addresses && (addr_count != 0)) if (!addresses && (addr_count != 0))
@ -4050,6 +4059,11 @@ if (dev->reflections == -1)
for (i = 0; i < addr_count; i++) for (i = 0; i < addr_count; i++)
memcpy(dev->filter_address[i], addresses[i], sizeof(ETH_MAC)); memcpy(dev->filter_address[i], addresses[i], sizeof(ETH_MAC));
dev->addr_count = addr_count; dev->addr_count = addr_count;
if (match_broadcast) {
memset(&dev->filter_address[addr_count], 0xFF, sizeof(ETH_MAC));
++addr_count;
}
dev->addr_count = addr_count;
/* store other flags */ /* store other flags */
dev->all_multicast = all_multicast; dev->all_multicast = all_multicast;
@ -4219,6 +4233,26 @@ fprintf(st, " Read Queue: High: %d\n", dev->read_queue.high);
fprintf(st, " Read Queue: Loss: %d\n", dev->read_queue.loss); fprintf(st, " Read Queue: Loss: %d\n", dev->read_queue.loss);
fprintf(st, " Peak Write Queue Size: %d\n", dev->write_queue_peak); fprintf(st, " Peak Write Queue Size: %d\n", dev->write_queue_peak);
#endif #endif
if (dev->error_needs_reset)
fprintf(st, " In Error Needs Reset: True\n");
if (dev->error_reopen_count)
fprintf(st, " Error Reopen Count: %d\n", (int)dev->error_reopen_count);
if (1) {
int i, count = 0;
ETH_MAC zeros = {0, 0, 0, 0, 0, 0};
char buffer[20];
for (i = 0; i < ETH_FILTER_MAX; i++) {
if (memcmp(zeros, &dev->filter_address[i], sizeof(ETH_MAC))) {
eth_mac_fmt(&dev->filter_address[i], buffer);
fprintf(st, " MAC Filter[%2d]: %s\n", count++, buffer);
}
}
}
if (dev->all_multicast)
fprintf(st, " All Multicast mode: Enabled\n");
if (dev->promiscuous)
fprintf(st, " Promiscuous mode: Enabled\n");
if (dev->bpf_filter) if (dev->bpf_filter)
fprintf(st, " BPF Filter: %s\n", dev->bpf_filter); fprintf(st, " BPF Filter: %s\n", dev->bpf_filter);
#if defined(HAVE_SLIRP_NETWORK) #if defined(HAVE_SLIRP_NETWORK)

View file

@ -342,11 +342,17 @@ t_stat eth_filter (ETH_DEV* dev, int addr_count, /* set filter on incomin
ETH_MAC* const addresses, ETH_MAC* const addresses,
ETH_BOOL all_multicast, ETH_BOOL all_multicast,
ETH_BOOL promiscuous); ETH_BOOL promiscuous);
t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, /* set filter on incoming packets with AUTODIN II based hash */ t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, /* set filter on incoming packets with hash */
ETH_MAC* const addresses, ETH_MAC* const addresses,
ETH_BOOL all_multicast, ETH_BOOL all_multicast,
ETH_BOOL promiscuous, ETH_BOOL promiscuous,
ETH_MULTIHASH* const hash); ETH_MULTIHASH* const hash); /* AUTODIN II based 8 byte imperfect hash */
t_stat eth_filter_hash_ex (ETH_DEV* dev, int addr_count,/* set filter on incoming packets with hash */
ETH_MAC* const addresses,
ETH_BOOL all_multicast,
ETH_BOOL promiscuous,
ETH_BOOL match_broadcast,
ETH_MULTIHASH* const hash); /* AUTODIN II based 8 byte imperfect hash */
t_stat eth_check_address_conflict (ETH_DEV* dev, t_stat eth_check_address_conflict (ETH_DEV* dev,
ETH_MAC* const address); ETH_MAC* const address);
const char *eth_version (void); /* Version of dynamically loaded library (pcap) */ const char *eth_version (void); /* Version of dynamically loaded library (pcap) */