Commit 430c8be4 authored by Michal Wasiak's avatar Michal Wasiak Committed by Adam Wujek

RTU: export mirror about ports' in shmem

update:
--wrs_dump_shmem
--wrs_vlans (print info about untag)
Signed-off-by: 's avatarMichal Wasiak <michal.wasiak@gmail.com>
parent 8febd611
......@@ -63,6 +63,7 @@ static inline uint8_t *mac_clean(uint8_t mac[ETH_ALEN])
char *mac_to_string(uint8_t mac[ETH_ALEN]);
char *mac_to_buffer(uint8_t mac[ETH_ALEN], char buffer[ETH_ALEN_STR]);
char *mac_to_buffer_no_colons(uint8_t mac[ETH_ALEN], char buffer[2*ETH_ALEN+1]);
int mac_from_str(uint8_t *tomac, const char *fromstr);
int mac_verify(char *mac_str);
int mac_to_lower(char *mac_str);
......
......@@ -18,6 +18,42 @@
#define ETH_ALEN 6
#define ETH_ALEN_STR 18
#define VALID_CONFIG 1<<31
#define VALID_QMODE 1<<0
#define VALID_PRIO 1<<1
#define VALID_VID 1<<2
#define VALID_FID 1<<3
#define VALID_UNTAG 1<<4
#define VALID_PMASK 1<<5
#define VALID_DROP 1<<6
#define QMODE_ACCESS 0
#define QMODE_TRUNK 1
#define QMODE_DISABLED 2
#define QMODE_UNQ 3
#define QMODE_INVALID 4
#define RTU_VID_MIN 0
#define RTU_VID_MAX 4094
#define RTU_FID_MIN 0
#define RTU_FID_MAX 4094
#define RTU_PRIO_MIN 0
#define RTU_PRIO_MAX 7
#define RTU_PRIO_DISABLE -1
#define PORT_PRIO_MIN RTU_PRIO_MIN
#define PORT_PRIO_MAX RTU_PRIO_MAX
#define PORT_PRIO_DISABLE RTU_PRIO_DISABLE
#define PORT_VID_MIN RTU_VID_MIN
#define PORT_VID_MAX RTU_VID_MAX
#define RTU_PMASK_MIN 0
#define RTU_PMASK_MAX(n_ports) ((1 << n_ports) - 1)
/* RTU entry address */
struct rtu_addr {
int hash;
......@@ -137,15 +173,30 @@ struct rtu_mirror_info {
uint32_t dmask; /* Destination port mask */
};
/**
* \brief RTU port configuration
*/
struct rtu_port_entry {
uint8_t qmode; /* q mode of a port */
uint8_t fix_prio; /* is fix priority set */
uint8_t prio; /* VLAN priority */
uint8_t untag; /* untag */
uint16_t pvid; /* PVID */
uint8_t mac[ETH_ALEN]; /* MAC of a port */
};
/* This is the overall structure stored in shared memory */
#define RTU_SHMEM_VERSION 4 /* Version 3, changed wrs_shm_head */
#define RTU_SHMEM_VERSION 5 /* Version 5, added rtu_ports */
struct rtu_shmem_header {
struct rtu_filtering_entry *filters;
struct rtu_vlan_table_entry *vlans;
struct rtu_mirror_info *mirror;
struct rtu_port_entry *rtu_ports;
uint32_t rtu_nports;
unsigned long filters_offset;
unsigned long vlans_offset;
unsigned long mirror_offset;
unsigned long rtu_ports_offset;
};
#endif /* __LIBWR_RTU_SHMEM_H__ */
......@@ -53,6 +53,17 @@ char *mac_to_buffer(uint8_t mac[ETH_ALEN], char buffer[ETH_ALEN_STR])
return buffer;
}
/**
* \brief Write mac address into a buffer to avoid concurrent access on static variable.
*/
char *mac_to_buffer_no_colons(uint8_t mac[ETH_ALEN], char buffer[2*ETH_ALEN+1])
{
if (mac && buffer)
snprintf(buffer, ETH_ALEN_STR, "%02x%02x%02x%02x%02x%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return buffer;
}
/**
* \brief Function to retrieve mac address from text input (argument in terminal)
*/
......
......@@ -76,6 +76,16 @@ char *spll_align_state_to_name[SPLL_ALIGN_STATE_MAX_N] = {
[ALIGN_STATE_WAIT_PLOCK] = "wait plock",
};
/* index of a the greatest number describing the qmode +1 */
#define RTU_QMODE_MAX 5
char *rtu_qmode_to_name[RTU_QMODE_MAX] = {
[QMODE_ACCESS] = "access",
[QMODE_TRUNK] = "trunk",
[QMODE_DISABLED] = "disabled",
[QMODE_UNQ] = "unqualified",
[QMODE_INVALID] = "invalid",
};
static int dump_all_rtu_entries = 0; /* rtu exports 4096 vlans and 2048 htab
entries */
......@@ -355,6 +365,20 @@ void dump_one_field(void *addr, struct dump_info *info, char *info_prefix)
printf("Unknown(%d)\n", i);
}
break;
case dump_type_rtu_qmode:
i = *(uint32_t *)p;
switch (i) {
case QMODE_ACCESS:
case QMODE_TRUNK:
case QMODE_DISABLED:
case QMODE_UNQ:
case QMODE_INVALID:
printf("%s(%d)\n", rtu_qmode_to_name[i], i);
break;
default:
printf("Unknown(%d)\n", i);
}
break;
case dump_type_array_int:
{
int *size = addr + info->size;
......@@ -624,6 +648,17 @@ struct dump_info mirror_info[] = {
DUMP_FIELD(uint32_t, dmask),
};
#undef DUMP_STRUCT
#define DUMP_STRUCT struct rtu_port_entry
struct dump_info rtu_port_info[] = {
DUMP_FIELD(rtu_qmode, qmode),
DUMP_FIELD(yes_no, fix_prio),
DUMP_FIELD(UInteger8, prio),
DUMP_FIELD(uint16_t, pvid),
DUMP_FIELD_SIZE(bina, mac, ETH_ALEN),
DUMP_FIELD(yes_no, untag),
};
int dump_rtu_mem(struct wrs_shm_head *head)
{
struct rtu_shmem_header *rtu_h;
......@@ -631,7 +666,9 @@ int dump_rtu_mem(struct wrs_shm_head *head)
struct rtu_filtering_entry *rtu_filters_cur;
struct rtu_vlan_table_entry *rtu_vlans;
struct rtu_mirror_info *rtu_mirror;
struct rtu_port_entry *rtu_ports;
int i, j;
int nports;
char prefix[64];
if (head->version != RTU_SHMEM_VERSION) {
......@@ -643,12 +680,20 @@ int dump_rtu_mem(struct wrs_shm_head *head)
rtu_filters = wrs_shm_follow(head, rtu_h->filters);
rtu_vlans = wrs_shm_follow(head, rtu_h->vlans);
rtu_mirror = wrs_shm_follow(head, rtu_h->mirror);
rtu_ports = wrs_shm_follow(head, rtu_h->rtu_ports);
if ((!rtu_filters) || (!rtu_vlans) || (!rtu_mirror)) {
fprintf(stderr, "dump rtu: cannot follow pointer in shm\n");
return -1;
}
/* get number of ports from rtu */
nports = rtu_h->rtu_nports;
if (nports <= 0) {
fprintf(stderr, "dump rtu: unable to get number of ports\n");
return -1;
}
/* dump shmem header*/
dump_many_fields(head, shm_head, ARRAY_SIZE(shm_head),"rtu.shm");
......@@ -678,6 +723,12 @@ int dump_rtu_mem(struct wrs_shm_head *head)
dump_many_fields(rtu_mirror, mirror_info, ARRAY_SIZE(mirror_info),
prefix);
for (i = 0; i < nports; i++, rtu_ports++) {
sprintf(prefix,"rtu.ports.%d", i + 1);
dump_many_fields(rtu_ports, rtu_port_info,
ARRAY_SIZE(rtu_port_info), prefix);
}
return 0;
}
......
......@@ -81,6 +81,7 @@ enum dump_type {
dump_type_spll_align_state,
/* rtu_filtering_entry enumerations */
dump_type_rtu_filtering_entry_dynamic,
dump_type_rtu_qmode,
dump_type_array_int,
/* scaledPicoseconds */
dump_type_scaledPicoseconds,
......
......@@ -29,6 +29,7 @@
#include <ctype.h>
#include <minipc.h>
#include <rtud_exports.h>
#include <rtu_drv.h>
#include "regs/endpoint-regs.h"
#include <libwr/switch_hw.h>
......@@ -39,6 +40,7 @@
#include <libwr/rtu_shmem.h>
#include <libwr/config.h>
#include <libwr/wrs-msg.h>
#include <libwr/mac.h>
static struct minipc_ch *rtud_ch;
static struct rtu_vlans_t *rtu_vlans = NULL;
......@@ -108,7 +110,10 @@ static int read_dot_config(char *dot_config_file);
static int read_dot_config_vlans(int vlan_min, int vlan_max);
struct rtu_vlan_table_entry *vlan_tab_shm;
struct rtu_port_entry *rtu_ports_shm;
struct wrs_shm_head *rtu_shmem_p;
struct rtu_shmem_header *rtu_hdr;
static inline int nextport(int i, unsigned long pmask) /* helper for for_each_port() below */
{
......@@ -164,7 +169,6 @@ int main(int argc, char *argv[])
{
int c, i, arg;
unsigned long conf_pmask = 0; /* current '--port' port mask */
struct rtu_shmem_header *rtu_hdr;
int n_wait = 0;
int ret, display_updates = 1; /* by default, display updates */
char *prgname;
......@@ -233,6 +237,14 @@ int main(int argc, char *argv[])
exit(1);
}
/* get rtu ports array */
rtu_ports_shm = wrs_shm_follow(rtu_shmem_p, rtu_hdr->rtu_ports);
if (!rtu_ports_shm) {
pr_error("cannot follow pointer to ports configuration in RTU's shmem\n");
exit(1);
}
if (shw_fpga_mmap_init() < 0) {
pr_error("Can't access device memory\n");
exit(1);
......@@ -314,7 +326,7 @@ int main(int argc, char *argv[])
break;
case OPT_RTU_PMASK:
ret = check_rtu("pmask", optarg, RTU_PMASK_MIN,
RTU_PMASK_MAX);
RTU_PMASK_MAX(NPORTS));
if (ret < 0)
exit(1);
set_rtu_vlan(-1, -1, ret, 0, -1, 0, VALID_PMASK);
......@@ -582,7 +594,7 @@ static int print_help(char *prgname)
fprintf(stderr, "\t --rfid <%d..%d> assign fid to configured VLAN\n",
RTU_FID_MIN, RTU_FID_MAX);
fprintf(stderr, "\t --rmask <0x%x..0x%x> ports belonging to configured VLAN\n",
RTU_PMASK_MIN, RTU_PMASK_MAX);
RTU_PMASK_MIN, RTU_PMASK_MAX(NPORTS));
fprintf(stderr, "\t --rdrop <0|1> don't drop or drop frames on VLAN (note that frame can belong\n"
"\t to a VID as a consequence of per-port Endpoint configuration)\n");
fprintf(stderr, "\t --rprio <%d|%d..%d> force priority for VLAN; -1 cancels priority override\n",
......@@ -693,49 +705,21 @@ static void print_config_vlan(void)
printf("\n");
}
static uint32_t ep_read(int ep, int offset)
{
return _fpga_readl(0x30000 + ep * 0x400 + offset);
}
static void ep_write(int ep, int offset, uint32_t value)
{
_fpga_writel(0x30000 + ep * 0x400 + offset, value);
}
static int apply_settings(struct s_port_vlans *vlans)
static int apply_settings(struct s_port_vlans *ports)
{
int ep;
uint32_t v, r;
int ret_val;
for_each_port(ep) {
/* VCR0 */
r = offsetof(struct EP_WB, VCR0);
v = ep_read(ep, r);
if (vlans[ep].valid_mask & VALID_QMODE)
v = (v & ~EP_VCR0_QMODE_MASK) | EP_VCR0_QMODE_W(vlans[ep].pmode);
if (vlans[ep].valid_mask & VALID_PRIO) {
if (vlans[ep].fix_prio)
v |= EP_VCR0_FIX_PRIO;
else
v &= ~EP_VCR0_FIX_PRIO;
v = (v & ~EP_VCR0_PRIO_VAL_MASK) | EP_VCR0_PRIO_VAL_W(vlans[ep].prio_val);
}
if (vlans[ep].valid_mask & VALID_VID)
v = (v & ~EP_VCR0_PVID_MASK) | EP_VCR0_PVID_W(vlans[ep].vid);
ep_write(ep, r, v);
/* VCR1: loop over the whole bitmask */
if (vlans[ep].valid_mask & VALID_UNTAG) {
int i;
r = offsetof(struct EP_WB, VCR1);
for (i = 0;i < 4096/16; i++) {
if (vlans[ep].untag_mask)
ep_write(ep, r, (0xffff << 10) | i);
else
ep_write(ep, r, (0x0000 << 10) | i);
}
}
minipc_call(rtud_ch, MINIPC_TIMEOUT, &rtud_export_port_cfg, &ret_val,
ep,
ports[ep].valid_mask,
ports[ep].pmode,
ports[ep].fix_prio,
ports[ep].prio_val,
ports[ep].vid,
ports[ep].untag_mask
);
}
config_rtud();
......@@ -833,21 +817,43 @@ static void list_rtu_vlans(void)
static void list_p_vlans(void)
{
uint32_t v, r;
unsigned ii;
unsigned retries = 0;
struct rtu_port_entry ports_tab_local[HAL_MAX_PORTS];
int rtu_nports_local;
char mac_buffer[ETH_ALEN_STR];
int ep;
printf("# QMODE FIX_PRIO PRIO PVID MAC\n");
printf("#-----------------------------------------------\n");
for (ep = 0; ep < NPORTS; ep++) {
r = offsetof(struct EP_WB, VCR0);
v = ep_read(ep, r);
printf("wri%-2i %i %6.6s %i %i %4i %04x%08x\n",
ep + 1, v & 3, qmode_names[v & 3],
v & EP_VCR0_FIX_PRIO ? 1 : 0,
EP_VCR0_PRIO_VAL_R(v),
EP_VCR0_PVID_R(v),
(int)ep_read(ep, offsetof(struct EP_WB, MACH)),
(int)ep_read(ep, offsetof(struct EP_WB, MACL)));
/* read data, with the sequential lock to have all data consistent */
while (1) {
ii = wrs_shm_seqbegin(rtu_shmem_p);
memcpy(&ports_tab_local, rtu_ports_shm,
HAL_MAX_PORTS * sizeof(*rtu_ports_shm));
rtu_nports_local = rtu_hdr->rtu_nports;
retries++;
if (retries > 100) {
pr_error("couldn't read consistent data from RTU's "
"shmem. Use inconsistent\n");
break; /* use inconsistent data */
}
if (!wrs_shm_seqretry(rtu_shmem_p, ii))
break; /* consistent read */
usleep(1000);
}
printf("# QMODE FIX_PRIO PRIO PVID MAC UNTAG\n");
printf("#------------------------------------------------------------\n");
for (ep = 0; ep < rtu_nports_local; ep++) {
printf("wri%-2i %i %6.6s %i %i %4i %s %i\n",
ep + 1,
ports_tab_local[ep].qmode,
qmode_names[ports_tab_local[ep].qmode],
ports_tab_local[ep].fix_prio,
ports_tab_local[ep].prio,
ports_tab_local[ep].pvid,
mac_to_buffer_no_colons(ports_tab_local[ep].mac, mac_buffer),
ports_tab_local[ep].untag
);
}
return;
}
......@@ -862,9 +868,9 @@ static void print_hp_mask(void)
pr_error("failed to read HP mask, ret %d\n", ret);
exit(1);
}
printf("#-----------------------------------------------\n");
printf("#------------------------------------------------------------\n");
printf("# HP mask: 0x%02x\n", hp_mask);
printf("#-----------------------------------------------\n");
printf("#------------------------------------------------------------\n");
}
static void default_vlan_config(void)
......@@ -877,29 +883,20 @@ static void default_vlan_config(void)
static int clear_all(void)
{
uint32_t r;
int val, i;
int ep;
int ret_val, i;
for (i = 0; i < NUM_VLANS; i++) {
if ((vlan_tab_shm[i].drop != 0)
&& (vlan_tab_shm[i].port_mask == 0x0))
continue;
minipc_call(rtud_ch, MINIPC_TIMEOUT,
&rtud_export_vlan_entry, &val, i,
&rtud_export_vlan_entry, &ret_val, i,
vlan_tab_shm[i].fid, 0, 1, 0, 0, 0);
}
/* cancel tagging/untagging in all endpoints*/
for (ep = 0; ep < NPORTS; ep++) {
r = offsetof(struct EP_WB, VCR0);
ep_write(ep, r, 0x3 /* QMODE */);
minipc_call(rtud_ch, MINIPC_TIMEOUT, &rtud_export_port_cfg_clear_all, &ret_val);
r = offsetof(struct EP_WB, VCR1);
for (i = 0;i < 4096/16; i++) {
ep_write(ep, r, (0x0000 << 10) | i); /* no untag */
}
}
return 0;
}
......@@ -1279,7 +1276,8 @@ static int read_dot_config_vlans(int vlan_min, int vlan_max)
if (!libwr_cfg_convert2("VLANS_VLAN%04d", "ports",
LIBWR_STRING, buff, vlan)) {
parse_mask(buff, &pmask);
if (pmask < RTU_PMASK_MIN || pmask > RTU_PMASK_MAX) {
if (pmask < RTU_PMASK_MIN
|| pmask > RTU_PMASK_MAX(NPORTS)) {
pr_error("invalid port mask 0x%lx (\"%s\") for"
" vlan %4d\n", pmask, buff, vlan);
return -1;
......
......@@ -23,23 +23,8 @@
#define NPORTS 18
#define QMODE_ACCESS 0
#define QMODE_TRUNK 1
#define QMODE_DISABLED 2
#define QMODE_UNQ 3
#define QMODE_INVALID 4
#define MINIPC_TIMEOUT 200
#define VALID_CONFIG 1<<31
#define VALID_QMODE 1<<0
#define VALID_PRIO 1<<1
#define VALID_VID 1<<2
#define VALID_FID 1<<3
#define VALID_UNTAG 1<<4
#define VALID_PMASK 1<<5
#define VALID_DROP 1<<6
#define PORT_MASK(x) (1<<(x))
#define OPT_HELP 'h'
......@@ -60,26 +45,6 @@
#define OPT_RTU_HP_MASK 30
#define OPT_FILE_READ 'f'
#define PORT_PRIO_MIN 0
#define PORT_PRIO_MAX 7
#define PORT_PRIO_DISABLE -1
#define PORT_VID_MIN 0
#define PORT_VID_MAX 4094
#define RTU_VID_MIN 0
#define RTU_VID_MAX 4094
#define RTU_FID_MIN 0
#define RTU_FID_MAX 4094
#define RTU_PRIO_MIN 0
#define RTU_PRIO_MAX 7
#define RTU_PRIO_DISABLE -1
#define RTU_PMASK_MIN 0
#define RTU_PMASK_MAX ((1 << NPORTS) - 1)
/* struct for ranges of VLAN sets used in dot-config */
struct vlan_sets {
char *name;
......
......@@ -52,9 +52,26 @@
// Default aging time resolution [secs]
#define DEFAULT_AGING_RES 20
// Used for clean_*() functions
#define SHM_NOT_LOCK 0
#define SHM_LOCK 1
// Keeping in mind year 2038
#define time_after(a,b) ((long)(b) - (long)(a) < 0)
extern struct wrs_shm_head *hal_head;
extern struct hal_port_state *hal_ports;
extern int hal_nports_local;
/**
* \brief Pointer to shmem, used for write locking.
*/
extern struct wrs_shm_head *rtu_shmem_p;
/**
* Mirror of port configuration
*/
extern struct rtu_port_entry *ports_cfg;
/**
* \brief RTU request: input for the RTU
*/
......
......@@ -45,14 +45,17 @@
#include <libwr/switch_hw.h>
#include <libwr/shmem.h>
#include <libwr/hal_shmem.h>
#include <libwr/rtu_shmem.h>
#include <libwr/wrs-msg.h>
#include <fpga_io.h>
#include <regs/rtu-regs.h>
#include <regs/endpoint-regs.h>
#include "rtu_drv.h"
#include "wr_rtu.h"
static void write_mfifo_addr(uint32_t zbt_addr);
static void write_mfifo_data(uint32_t word);
......@@ -62,15 +65,18 @@ static uint32_t mac_entry_word2_w(struct rtu_filtering_entry *ent);
static uint32_t mac_entry_word3_w(struct rtu_filtering_entry *ent);
static uint32_t mac_entry_word4_w(struct rtu_filtering_entry *ent);
static char *qmode_names[] = {"ACCESS ",
"TRUNK ",
"disabled ",
"unqualified"};
static char *yes_no[] ={"no ",
"yes "};
/*
* Used to communicate to RTU UFIFO IRQ handler device at kernel space
*/
static int fd;
extern struct wrs_shm_head *hal_head;
extern struct hal_port_state *hal_ports;
extern int hal_nports_local;
#define HAL_SHMEM_TOTAL_US (20000000) // 20sec
#define HAL_SHMEM_SLEEP_US (250000) // 250ms
#define HAL_SHMEM_RETRIES (HAL_SHMEM_TOTAL_US/HAL_SHMEM_SLEEP_US)
......@@ -696,6 +702,152 @@ int rtu_get_mirroring(int *en, uint32_t *imask, uint32_t *emask, uint32_t *dmask
return 0;
}
static void print_config_rtu(int port, uint8_t valid_mask, struct rtu_port_entry *rtu_ports)
{
int i;
i=port;
pr_debug("Updates applied for port: %4d ", i+1);
pr_debug("pmode: ");
if (valid_mask & VALID_QMODE)
pr_debug("%s ", qmode_names[rtu_ports[i].qmode & 0x3]);
else
pr_debug("[No update] ");
pr_debug("fix_prio: ");
if (valid_mask & VALID_PRIO)
pr_debug("%s ", yes_no[rtu_ports[i].fix_prio & 0x1]);
else
pr_debug("[No update] ");
pr_debug("prio_val: ");
if (valid_mask & VALID_PRIO)
pr_debug("%2d ", rtu_ports[i].prio);
else
pr_debug("[No update] ");
pr_debug("vid: ");
if (valid_mask & VALID_VID)
pr_debug("%4d ", rtu_ports[i].pvid);
else
pr_debug("[No update] ");
pr_debug("untag: ");
if (valid_mask & VALID_UNTAG)
pr_debug("%s ", yes_no[rtu_ports[i].untag]);
else
pr_debug("[No update] ");
pr_debug("\n");
}
static uint32_t ep_read(int ep, int offset)
{
return _fpga_readl(0x30000 + ep * 0x400 + offset);
}
static void ep_write(int ep, int offset, uint32_t value)
{
_fpga_writel(0x30000 + ep * 0x400 + offset, value);
}
static void rtu_write_port_cfg_hw(uint8_t hw_index)
{
uint32_t v, r;
int i;
r = offsetof(struct EP_WB, VCR0);
v = ep_read(hw_index, r);
v = (v & ~EP_VCR0_QMODE_MASK) | EP_VCR0_QMODE_W(ports_cfg[hw_index].qmode);
if (ports_cfg[hw_index].fix_prio)
v |= EP_VCR0_FIX_PRIO;
else
v &= ~EP_VCR0_FIX_PRIO;
v = (v & ~EP_VCR0_PRIO_VAL_MASK) | EP_VCR0_PRIO_VAL_W(ports_cfg[hw_index].prio);
v = (v & ~EP_VCR0_PVID_MASK) | EP_VCR0_PVID_W(ports_cfg[hw_index].pvid);
ep_write(hw_index, r, v);
/* VCR1: loop over the whole bitmask */
r = offsetof(struct EP_WB, VCR1);
for (i = 0;i < 4096/16; i++) {
if (ports_cfg[hw_index].untag)
ep_write(hw_index, r, (0xffff << 10) | i);
else
ep_write(hw_index, r, (0x0000 << 10) | i);
}
}
void rtu_write_port_config(uint8_t hw_index, /* indexed from 0 to 17 */
uint8_t valid_mask, /* mask of valid settings */
uint8_t qmode, /* q mode of a port */
uint8_t fix_prio, /* is fix priority set */
uint8_t prio, /* VLAN priority */
uint16_t pvid, /* PVID */
uint8_t untag /* untag */
)
{
wrs_shm_write(rtu_shmem_p, WRS_SHM_WRITE_BEGIN);
/* update masks in SHM only for fields included in the valid_mask */
if (valid_mask & VALID_QMODE)
ports_cfg[hw_index].qmode = qmode;
if (valid_mask & VALID_PRIO) {
ports_cfg[hw_index].fix_prio = fix_prio;
ports_cfg[hw_index].prio = prio;
}
if (valid_mask & VALID_VID)
ports_cfg[hw_index].pvid = pvid;
if (valid_mask & VALID_UNTAG)
ports_cfg[hw_index].untag = untag;
print_config_rtu(hw_index, valid_mask, ports_cfg);
rtu_write_port_cfg_hw(hw_index);
wrs_shm_write(rtu_shmem_p, WRS_SHM_WRITE_END);
}
static void rtu_read_mac_from_ep(int hw_index, uint8_t mac[ETH_ALEN])
{
uint32_t tmp;
tmp = ep_read(hw_index, offsetof(struct EP_WB, MACH)),
mac[0] = ((tmp >> 8) & 0xff);
mac[1] = (tmp & 0xff);
tmp = ep_read(hw_index, offsetof(struct EP_WB, MACL));
mac[2] = ((tmp >> 24) & 0xff);
mac[3] = ((tmp >> 16) & 0xff);
mac[4] = ((tmp >> 8) & 0xff);
mac[5] = (tmp & 0xff);
}
/**
* Port config initialization.
*/
void rtu_clean_ports(int lock)
{
uint8_t hw_index;
if (lock & SHM_LOCK)
wrs_shm_write(rtu_shmem_p, WRS_SHM_WRITE_BEGIN);
memset(ports_cfg, 0, sizeof(*ports_cfg) * HAL_MAX_PORTS);
for (hw_index = 0; hw_index < hal_nports_local; hw_index++) {
ports_cfg[hw_index].qmode = QMODE_UNQ;
ports_cfg[hw_index].fix_prio = 0;
ports_cfg[hw_index].prio = 0;
ports_cfg[hw_index].pvid = 0;
ports_cfg[hw_index].untag = 0;
rtu_write_port_cfg_hw(hw_index);
/* read MAC from ep */
rtu_read_mac_from_ep(hw_index, ports_cfg[hw_index].mac);
}
if (lock & SHM_LOCK)
wrs_shm_write(rtu_shmem_p, WRS_SHM_WRITE_END);
}
//---------------------------------------------
// Private Methods
//---------------------------------------------
......
......@@ -101,4 +101,15 @@ int rtu_enable_mirroring(int ena);
int rtu_cfg_mirroring(struct rtu_mirror_info *cfg);
int rtu_get_mirroring(int *en, uint32_t *imask, uint32_t *emask, uint32_t *dmask);
// PORT CONFIG
void rtu_write_port_config(uint8_t hw_index, /* indexed from 0 to 17 */
uint8_t valid_mask, /* mask of valid settings */
uint8_t qmode, /* q mode of a port */
uint8_t fix_prio, /* is fix priority set */
uint8_t prio, /* VLAN priority */
uint16_t pvid, /* PVID */
uint8_t untag /* untag */
);
void rtu_clean_ports(int lock);
#endif /*__WHITERABBIT_RTU_DRV_H*/
......@@ -41,6 +41,7 @@
#include <libwr/wrs-msg.h>
#include <libwr/shmem.h>
#include <libwr/rtu_shmem.h>
#include <libwr/hal_shmem.h>
#include <libwr/util.h>
#include "rtu_fd.h"
......@@ -51,9 +52,6 @@
#define HW_WRITE_REQ 0
#define HW_REMOVE_REQ 1
// Used for clean_*() functions
#define SHM_NOT_LOCK 0
#define SHM_LOCK 1
/**
* \brief Filtering Database entry handle.
*/
......@@ -101,15 +99,20 @@ static struct rtu_vlan_table_entry *vlan_tab;
*/
static struct rtu_mirror_info *mirror_cfg;
/**
* Mirror of port configuration
*/
struct rtu_port_entry *ports_cfg;
/**
* \brief Mutex used to synchronise concurrent access to the filtering database.
*/
static pthread_mutex_t fd_mutex;
/**
* \brief Pointer to shmem, user for write locking.
* \brief Pointer to shmem, used for write locking.
*/
static struct wrs_shm_head *rtu_shmem_p;
struct wrs_shm_head *rtu_shmem_p;
static struct hw_req *tail(struct hw_req *head);
static void clean_list(struct hw_req *head);
......@@ -210,7 +213,36 @@ int rtu_fd_init(uint16_t poly, unsigned long aging)
mirror_cfg = wrs_shm_follow(rtu_shmem_p, rtu_hdr->mirror);
}
if ((!rtu_htab) || (!vlan_tab) || (!mirror_cfg)) {
if (!rtu_hdr->rtu_ports) {
/* for first RTUd run */
pr_info("Allocating a new, port config\n");
ports_cfg = wrs_shm_alloc(rtu_shmem_p,
sizeof(*ports_cfg) * HAL_MAX_PORTS);
rtu_hdr->rtu_ports = ports_cfg;
rtu_hdr->rtu_ports_offset =
(void *)ports_cfg - (void *)rtu_shmem_p;
pr_debug("Clean ports database.\n");
rtu_hdr->rtu_nports = hal_nports_local;
rtu_clean_ports(SHM_NOT_LOCK); /* clean port ports config,
shem already locked */
} else {
pr_info("Using existing port config.\n");
/* next RTUd runs */
ports_cfg = wrs_shm_follow(rtu_shmem_p, rtu_hdr->rtu_ports);
if (rtu_hdr->rtu_nports != hal_nports_local) {
pr_warning("Number of ports reported by HAL (%d) and "
"saved previously by RTUs (%d) does not "
"match! Clean all ports information in RTU",
hal_nports_local,
rtu_hdr->rtu_nports);
rtu_hdr->rtu_nports = hal_nports_local;
/* clean port portsconfig, shem already locked */
rtu_clean_ports(SHM_NOT_LOCK);
}
}
if ((!rtu_htab) || (!vlan_tab) || (!mirror_cfg) || (!ports_cfg)) {
pr_error("%s: Cannot allocate mem in shmem\n", __func__);
return -1;
}
......
......@@ -56,8 +56,8 @@ int rtudexp_clear_entries(const struct minipc_pd *pd,
int type = (int)args[1];
int *p_ret = (int *)ret; /* force pointed to int type */
if (0 > port || port > 18) { /* 18 ports + CPU */
pr_error("Wrong port mask 0x%x\n", port);
if (0 > port || port > hal_nports_local) { /* 18 ports + CPU */
pr_error("Wrong port wri%d\n", port + 1);
*p_ret = -1;
return *p_ret;
}
......@@ -370,6 +370,103 @@ int rtudexp_mirror(const struct minipc_pd *pd, uint32_t *args, void *ret)
return *p_ret;
}
int rtudexp_port_cfg(const struct minipc_pd *pd, uint32_t *args, void *ret)
{
int *p_ret = (int *)ret;
uint8_t hw_index; /* indexed from 0 to 17 */
uint8_t valid_mask; /* mask of valid settings */
uint8_t qmode; /* q mode of a port */
uint8_t fix_prio; /* is fix priority set */
uint8_t prio; /* VLAN priority */
uint16_t pvid; /* PVID */
uint8_t untag; /* untag */
hw_index = (uint8_t)args[0];
valid_mask = (uint8_t)args[1];
qmode = (uint8_t)args[2];
fix_prio = (uint8_t)args[3];
prio = (uint8_t)args[4];
pvid = (uint16_t)args[5];
untag = (uint8_t)args[6];
*p_ret = 0;
pr_debug("Request for port configuration\n");
if (hw_index < 0 || hw_index > hal_nports_local) {
pr_error("Wrong port wri%d\n", hw_index + 1); /* 1.. */
*p_ret = -1;
return *p_ret;
}
/* check qmode range */
switch (qmode) {
case QMODE_ACCESS:
case QMODE_TRUNK:
case QMODE_DISABLED:
case QMODE_UNQ:
break;
default:
pr_error("Wrong qmode %d\n", qmode);
*p_ret = -1;
return *p_ret;
}
/* check fix_prio range */
switch (fix_prio) {
case 0:
case 1:
break;
default:
pr_error("Wrong fix_prio %d\n", fix_prio);
*p_ret = -1;
return *p_ret;
}
/* check prio range */
if (prio < PORT_VID_MIN || prio > PORT_PRIO_MAX) {
pr_error("Wrong prio %d\n", prio);
*p_ret = -1;
return *p_ret;
}
/* check pvid range */
if (pvid < PORT_VID_MIN || pvid > PORT_VID_MAX) {
pr_error("Wrong pvid %d\n", pvid);
*p_ret = -1;
return *p_ret;
}
/* check untag range */
switch (untag) {
case 0:
case 1:
break;
default:
pr_error("Wrong untag %d\n", untag);
*p_ret = -1;
return *p_ret;
}
rtu_write_port_config(hw_index,
valid_mask,
qmode,
fix_prio,
prio,
pvid,
untag);
return *p_ret;
}
int rtudexp_port_cfg_clear_all(const struct minipc_pd *pd, uint32_t *args, void *ret)
{
int *p_ret = (int *)ret;
rtu_clean_ports(SHM_LOCK);
return *p_ret;
}
int rtud_init_exports()
{
rtud_ch = minipc_server_create("rtud", 0);
......@@ -390,6 +487,8 @@ int rtud_init_exports()
MINIPC_EXP_FUNC(rtud_export_vlan_entry, rtudexp_vlan_entry);
MINIPC_EXP_FUNC(rtud_export_hp_mask, rtudexp_hp_mask);
MINIPC_EXP_FUNC(rtud_export_mirror, rtudexp_mirror);
MINIPC_EXP_FUNC(rtud_export_port_cfg, rtudexp_port_cfg);
MINIPC_EXP_FUNC(rtud_export_port_cfg_clear_all, rtudexp_port_cfg_clear_all);
return 0;
}
......
......@@ -44,7 +44,7 @@
#define RTU_SET_HP_MASK 1
#define RTU_GET_HP_MASK 2
/* Export of a function to set remove entry in rtu */
/* Export of a function to remove entries from rtu for a given port */
struct minipc_pd rtud_export_clear_entries = {
.name = "clear_entries",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
......@@ -146,4 +146,29 @@ struct minipc_pd rtud_export_mirror = {
},
};
/* Export of a function to configure port in rtu */
struct minipc_pd rtud_export_port_cfg = {
.name = "port_cfg",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
.args = {
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), /* hw_index */
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), /* valid_mask */
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), /* qmode */
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), /* fix_priority */
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), /* priority */
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), /* pvid */
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), /* untag */
MINIPC_ARG_END,
},
};
/* Export of a function to clear a port configuration in rtu */
struct minipc_pd rtud_export_port_cfg_clear_all = {
.name = "clear_entries",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
.args = {
MINIPC_ARG_END,
},
};
#endif
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