Commit a444be3e authored by Alessandro Rubini's avatar Alessandro Rubini

vlan: add one VLAN in Kconfig as an option

WARNING: wr_switch_defconfig doesn't build, this is fixed in next commit

Unfortunately this commit makes the internal communication between
minic and lan asymmetric: on receive the tag is discarded (and the
longer header falls into the payload) while on transmit it must be
provided by lan.c.

The reason is that on receive we can trim 4 bytes from the payload,
but on send we can't add 4 bytes without a memmove.  The functions
receive pointers to two different header structures, so hopefully
user errors will be signalled by the compiler.

Still, users interact with net.c, which hides vlan completely from
them.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 52ec2a38
......@@ -37,6 +37,13 @@ config WRC_VERBOSE
boolean
default y if WR_SWITCH
config VLAN
boolean
config VLAN_NR
int
default 10 if VLAN
default 0
# CONFIG_WR_SWITCH has no further options at all at this point
......@@ -301,7 +308,13 @@ config WRC_VERBOSE
help
This enables some more diagnostic messages. Normally off.
config VLAN
depends on DEVELOPER
boolean "Filter and rx/tx frames in a VLAN (as opposed to untagged)"
config VLAN_NR
depends on VLAN
int "Use this VLAN number for filter/tx/rx"
config SDB_STORAGE
depends on WR_NODE
......
......@@ -60,7 +60,8 @@ LDFLAGS_PLATFORM = -mmultiply-enabled -mbarrel-shift-enabled \
-nostdlib -T $(LDS-y)
# packet-filter rules depend on configuration; default is rules-plain
pfilter-y := rules-default.bin
pfilter-y := rules-novlan.bin
pfilter-$(CONFIG_VLAN) := rules-vlan.bin
export pfilter-y
all:
......
......@@ -10,6 +10,7 @@
#include <stdio.h>
#include <string.h>
#include <wrc.h>
#include <wrpc.h>
#include "types.h"
#include "board.h"
......@@ -288,20 +289,25 @@ int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size,
return n_recvd;
}
int minic_tx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t size,
int minic_tx_frame(struct wr_ethhdr_vlan *hdr, uint8_t *payload, uint32_t size,
struct hw_timestamp *hwts)
{
uint32_t d_hdr, mcr, nwords;
uint8_t ts_valid;
int i;
int i, hsize;
minic_new_tx_buffer();
memset((void *)minic.tx_head, 0x0, size + 16);
memset((void *)minic.tx_head + 4, 0, size < 60 ? 60 : size);
memcpy((void *)minic.tx_head + 4, hdr, ETH_HEADER_SIZE);
memcpy((void *)minic.tx_head + 4 + ETH_HEADER_SIZE, payload, size);
if (hdr->ethtype == htons(0x8100))
hsize = sizeof(struct wr_ethhdr_vlan);
else
hsize = sizeof(struct wr_ethhdr);
memset((void *)minic.tx_head, 0x0, size + hsize + 4);
memcpy((void *)minic.tx_head + 4, hdr, hsize);
memcpy((void *)minic.tx_head + 4 + hsize, payload, size);
size += hsize;
size += ETH_HEADER_SIZE;
if (size < 60)
size = 60;
......
......@@ -25,9 +25,17 @@ struct wr_ethhdr {
uint16_t ethtype;
};
struct wr_ethhdr_vlan {
uint8_t dstmac[6];
uint8_t srcmac[6];
uint16_t ethtype;
uint16_t tag;
uint16_t ethtype_2;
};
int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size,
struct hw_timestamp *hwts);
int minic_tx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t size,
int minic_tx_frame(struct wr_ethhdr_vlan *hdr, uint8_t * payload, uint32_t size,
struct hw_timestamp *hwts);
#endif
......@@ -43,6 +43,7 @@ struct wr_sockaddr {
// RAW ethertype
uint16_t ethertype;
uint16_t udpport;
uint16_t vlan;
};
struct sockq {
......
......@@ -35,6 +35,8 @@
# define is_wr_node 1
#endif
extern int wrc_vlan_number;
int wrc_mon_gui(void);
void shell_init(void);
int wrc_log_stats(void);
......
......@@ -241,6 +241,7 @@ int ptpd_netif_recvfrom(struct wrpc_socket *s, struct wr_sockaddr *from, void *d
q->avail += wrap_copy_in(data, q, size, data_length);
from->ethertype = ntohs(hdr.ethtype);
from->vlan = wrc_vlan_number; /* has been checked in rcvd frame */
memcpy(from->mac, hdr.srcmac, 6);
memcpy(from->mac_dest, hdr.dstmac, 6);
......@@ -276,12 +277,18 @@ int ptpd_netif_sendto(struct wrpc_socket * sock, struct wr_sockaddr *to, void *d
{
struct wrpc_socket *s = (struct wrpc_socket *)sock;
struct hw_timestamp hwts;
struct wr_ethhdr hdr;
struct wr_ethhdr_vlan hdr;
int rval;
memcpy(hdr.dstmac, to->mac, 6);
memcpy(hdr.srcmac, s->local_mac, 6);
hdr.ethtype = sock->bind_addr.ethertype;
if (wrc_vlan_number) {
hdr.ethtype = htons(0x8100);
hdr.tag = htons(wrc_vlan_number);
hdr.ethtype_2 = sock->bind_addr.ethertype; /* net order */
} else {
hdr.ethtype = sock->bind_addr.ethertype;
}
net_verbose("TX: socket %04x:%04x, len %i\n",
ntohs(s->bind_addr.ethertype),
s->bind_addr.udpport,
......@@ -309,16 +316,34 @@ int update_rx_queues()
struct hw_timestamp hwts;
static struct wr_ethhdr hdr;
int recvd, i, q_required;
static uint8_t payload[NET_MAX_SKBUF_SIZE - 32];
static uint8_t buffer[NET_MAX_SKBUF_SIZE - 32];
uint8_t *payload = buffer;
uint16_t size, port;
uint16_t ethtype, tag;
recvd =
minic_rx_frame(&hdr, payload, sizeof(payload),
minic_rx_frame(&hdr, buffer, sizeof(buffer),
&hwts);
if (recvd <= 0) /* No data received? */
return 0;
/* Remove the vlan tag, but make sure it's the right one */
ethtype = hdr.ethtype;
tag = 0;
if (ntohs(ethtype) == 0x8100) {
memcpy(&tag, buffer, 2);
memcpy(&hdr.ethtype, buffer + 2, 2);
payload += 4;
recvd -= 4;
}
if ((ntohs(tag) & 0xfff) != wrc_vlan_number) {
net_verbose("%s: want vlan %i, got %i: discard\n",
__func__, wrc_vlan_number,
ntohs(tag) & 0xfff);
return 0;
}
for (i = 0; i < ARRAY_SIZE(socks); i++) {
s = socks[i];
if (!s)
......
EB ?= no
SDBFS ?= no
CFLAGS = -Wall -ggdb -I../include
CFLAGS = -Wall -ggdb -I../include \
-include ../include/generated/autoconf.h
LDFLAGS = -lutil
ALL = genraminit genramvhd genrammif wrpc-uart-sw
ALL += wrpc-w1-read wrpc-w1-write
......
......@@ -212,7 +212,7 @@ enum pf_symbolic_regs {
/* The first set is used for straight comparisons */
FRAME_BROADCAST = R_1,
FRAME_OUR_MAC,
FRAME_TAGGED,
FRAME_OUR_VLAN,
FRAME_TYPE_IPV4,
FRAME_TYPE_PTP2,
FRAME_TYPE_ARP,
......@@ -363,7 +363,7 @@ static void pfilter_output(char *fname)
}
void pfilter_init(int mode, char *fname)
void pfilter_init_novlan(char *fname)
{
pfilter_new();
pfilter_nop();
......@@ -384,8 +384,8 @@ void pfilter_init(int mode, char *fname)
pfilter_cmp(2, 0xffff, 0xffff, AND, FRAME_BROADCAST);
/* Tagged is dropped. We'll invert the check in the vlan rule-set */
pfilter_cmp(6, 0x8100, 0xffff, MOV, FRAME_TAGGED);
pfilter_logic2(R_DROP, FRAME_TAGGED, MOV, R_ZERO);
pfilter_cmp(6, 0x8100, 0xffff, MOV, R_TMP);
pfilter_logic2(R_DROP, R_TMP, MOV, R_ZERO);
/* Identify some Ethertypes used later. */
pfilter_cmp(6, 0x88f7, 0xffff, MOV, FRAME_TYPE_PTP2);
......@@ -436,10 +436,54 @@ void pfilter_init(int mode, char *fname)
}
void pfilter_init_vlan(char *fname)
{
pfilter_new();
pfilter_nop();
/*
* This is a simplified set, for development,
* to allow me write vlan support in software.
* Mostly a subset of above set
*/
/* Local frame, using fake MAC: 12:34:56:78:9a:bc */
pfilter_cmp(0, 0x1234, 0xffff, MOV, FRAME_OUR_MAC);
pfilter_cmp(1, 0x5678, 0xffff, AND, FRAME_OUR_MAC);
pfilter_cmp(2, 0x9abc, 0xffff, AND, FRAME_OUR_MAC);
/* Broadcast frame */
pfilter_cmp(0, 0xffff, 0xffff, MOV, FRAME_BROADCAST);
pfilter_cmp(1, 0xffff, 0xffff, AND, FRAME_BROADCAST);
pfilter_cmp(2, 0xffff, 0xffff, AND, FRAME_BROADCAST);
/* Untagged is dropped. */
pfilter_cmp(6, 0x8100, 0xffff, MOV, R_TMP);
pfilter_logic2(R_DROP, R_TMP, NOT, R_ZERO);
/* Compare with our vlan */
pfilter_cmp(7, CONFIG_VLAN_NR, 0x0fff, MOV, FRAME_OUR_VLAN);
/* Identify some Ethertypes used later. */
pfilter_cmp(8, 0x88f7, 0xffff, MOV, FRAME_TYPE_PTP2);
pfilter_cmp(8, 0x0800, 0xffff, MOV, FRAME_TYPE_IPV4);
pfilter_cmp(8, 0x0806, 0xffff, MOV, FRAME_TYPE_ARP);
/* Loose match: keep all bcast, all our mac and all ptp ... */
pfilter_logic3(FRAME_FOR_CPU,
FRAME_OUR_MAC, OR, FRAME_BROADCAST, OR, FRAME_TYPE_PTP2);
/* .... but only for our current VLAN */
pfilter_logic2(R_CLASS(0), FRAME_FOR_CPU, AND, FRAME_OUR_VLAN);
pfilter_output(fname);
}
int main(int argc, char **argv) /* no arguments used currently */
{
prgname = argv[0];
pfilter_init(0, "rules-default.bin");
pfilter_init_novlan("rules-novlan.bin");
pfilter_init_vlan("rules-vlan.bin");
exit(0);
}
......@@ -44,6 +44,8 @@ int32_t sfp_deltaTx = 0;
int32_t sfp_deltaRx = 0;
uint32_t cal_phase_transition = 2389;
int wrc_vlan_number = CONFIG_VLAN_NR;
static uint32_t prev_nanos_for_profile;
static void wrc_initialize(void)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment