Commit 91dc866a authored by Alessandro Rubini's avatar Alessandro Rubini

userspace/wrsw_rtud: indented with Lindent

Stuff was seriously misaligned and hard to read. So Maciej agreed
about running ../../scripts/Lindent. This commit makes no modification
at all, even it changes both spaces/tabs and newlines.

Some comments still exceed 80 columns, which is bad for me, my screen and
my printer, but I'll only change if needed, at a later step.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent cb741022
......@@ -28,34 +28,36 @@
#include "mac.h"
#include <stdio.h>
/**
* \brief Helper function to convert mac address into a string
* WARNING: this returns static storage
*/
char *mac_to_string(uint8_t mac[ETH_ALEN])
{
static char str[40];
snprintf(str, 40, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
return str;
static char str[40];
snprintf(str, 40, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1],
mac[2], mac[3], mac[4], mac[5]);
return str;
}
/**
* \brief Write mac address into a buffer to avoid concurrent access on static variable.
*/
char *mac_to_buffer(uint8_t mac[ETH_ALEN],char buffer[ETH_ALEN_STR])
char *mac_to_buffer(uint8_t mac[ETH_ALEN], char buffer[ETH_ALEN_STR])
{
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;
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)
*/
int mac_from_str(uint8_t* tomac, const char *fromstr)
int mac_from_str(uint8_t * tomac, const char *fromstr)
{
if(tomac==0 || fromstr==0) return -1;
return sscanf(fromstr,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",tomac+0,tomac+1,tomac+2,tomac+3,tomac+4,tomac+5);
if (tomac == 0 || fromstr == 0)
return -1;
return sscanf(fromstr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", tomac + 0,
tomac + 1, tomac + 2, tomac + 3, tomac + 4, tomac + 5);
}
......@@ -27,7 +27,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WHITERABBIT_RTU_MAC_H
#define __WHITERABBIT_RTU_MAC_H
......@@ -43,34 +42,29 @@
*/
static inline int mac_equal(uint8_t a[ETH_ALEN], uint8_t b[ETH_ALEN])
{
return !memcmp(a, b, ETH_ALEN);
return !memcmp(a, b, ETH_ALEN);
}
/**
* \brief copies src mac address into dst mac address.
* @return pointer to dst mac address
*/
static inline uint8_t* mac_copy(uint8_t dst[ETH_ALEN], uint8_t src[ETH_ALEN])
static inline uint8_t *mac_copy(uint8_t dst[ETH_ALEN], uint8_t src[ETH_ALEN])
{
return memcpy(dst, src, ETH_ALEN);
return memcpy(dst, src, ETH_ALEN);
}
/**
* \brief Set MAC address to 00:00:00:00:00:00.
* @return pointer to mac address
*/
static inline uint8_t* mac_clean(uint8_t mac[ETH_ALEN])
static inline uint8_t *mac_clean(uint8_t mac[ETH_ALEN])
{
return memset(mac, 0x00, ETH_ALEN);
return memset(mac, 0x00, 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]);
int mac_from_str(uint8_t* tomac, const char *fromstr);
char *mac_to_buffer(uint8_t mac[ETH_ALEN], char buffer[ETH_ALEN_STR]);
int mac_from_str(uint8_t * tomac, const char *fromstr);
#endif /* __WHITERABBIT_RTU_MAC_H */
......@@ -70,11 +70,10 @@
#define TRACE_DBG(...)
#endif
/* RTU entry address */
struct rtu_addr {
int hash;
int bucket;
int hash;
int bucket;
};
/**
......@@ -82,94 +81,91 @@ struct rtu_addr {
*/
struct rtu_request {
int port_id; // physical port identifier
uint8_t src[ETH_ALEN]; // source MAC address
uint8_t dst[ETH_ALEN]; // destination MAC address
uint16_t vid; // VLAN ID from the packet header
int has_vid; // non-zero: VID is present,0:untagged packet (VID=0)
uint8_t prio; // packet priority (either assigned by the port
// or extracted from packet header)
int has_prio; // non-zero: priority present, 0:no priority defined
int port_id; // physical port identifier
uint8_t src[ETH_ALEN]; // source MAC address
uint8_t dst[ETH_ALEN]; // destination MAC address
uint16_t vid; // VLAN ID from the packet header
int has_vid; // non-zero: VID is present,0:untagged packet (VID=0)
uint8_t prio; // packet priority (either assigned by the port
// or extracted from packet header)
int has_prio; // non-zero: priority present, 0:no priority defined
};
/**
* \brief RTU Filtering Database Entry Object
*/
struct filtering_entry {
struct rtu_addr addr; // address of self in the RTU hashtable
int valid; // bit: 1 = entry is valid, 0: entry is
// invalid (empty)
int end_of_bucket; // bit: 1 = last entry in current bucket, stop
// search at this point
int is_bpdu; // bit: 1 = BPDU (or other non-STP-dependent
// packet)
uint8_t mac[ETH_ALEN]; // MAC address (for searching the bucketed
// hashtable)
uint8_t fid; // Filtering database ID (for searching the
// bucketed hashtable)
uint32_t port_mask_src; // port mask for source MAC addresses. Bits
// set to 1 indicate that packet having this
// MAC address can be forwarded from these
// corresponding ports. Ports having their
// bits set to 0 shall drop the packet.
uint32_t port_mask_dst; // port mask for destination MAC address. Bits
// set to 1 indicate to which physical ports
// the packet with matching destination MAC
// address shall be routed
int drop_when_source; // bit: 1 = drop the packet when source
// address matches
int drop_when_dest; // bit: 1 = drop the packet when destination
// address matches
int drop_unmatched_src_ports; // bit: 1 = drop the packet when it comes from
// source port different than specified in
// port_mask_src
uint32_t last_access_t; // time of last access to the rule (for aging)
int force_remove; // when true, the entry is to be removed immediately (
// aged out or destination port went down)
uint8_t prio_src; // priority (src MAC)
int has_prio_src; // priority value valid
int prio_override_src; // priority override (force per-MAC priority)
uint8_t prio_dst; // priority (dst MAC)
int has_prio_dst; // priority value valid
int prio_override_dst; // priority override (force per-MAC priority)
int dynamic;
int age;
struct rtu_addr addr; // address of self in the RTU hashtable
int valid; // bit: 1 = entry is valid, 0: entry is
// invalid (empty)
int end_of_bucket; // bit: 1 = last entry in current bucket, stop
// search at this point
int is_bpdu; // bit: 1 = BPDU (or other non-STP-dependent
// packet)
uint8_t mac[ETH_ALEN]; // MAC address (for searching the bucketed
// hashtable)
uint8_t fid; // Filtering database ID (for searching the
// bucketed hashtable)
uint32_t port_mask_src; // port mask for source MAC addresses. Bits
// set to 1 indicate that packet having this
// MAC address can be forwarded from these
// corresponding ports. Ports having their
// bits set to 0 shall drop the packet.
uint32_t port_mask_dst; // port mask for destination MAC address. Bits
// set to 1 indicate to which physical ports
// the packet with matching destination MAC
// address shall be routed
int drop_when_source; // bit: 1 = drop the packet when source
// address matches
int drop_when_dest; // bit: 1 = drop the packet when destination
// address matches
int drop_unmatched_src_ports; // bit: 1 = drop the packet when it comes from
// source port different than specified in
// port_mask_src
uint32_t last_access_t; // time of last access to the rule (for aging)
int force_remove; // when true, the entry is to be removed immediately (
// aged out or destination port went down)
uint8_t prio_src; // priority (src MAC)
int has_prio_src; // priority value valid
int prio_override_src; // priority override (force per-MAC priority)
uint8_t prio_dst; // priority (dst MAC)
int has_prio_dst; // priority value valid
int prio_override_dst; // priority override (force per-MAC priority)
int dynamic;
int age;
};
/**
* \brief RTU VLAN registration entry object
*/
struct vlan_table_entry {
uint32_t port_mask; // VLAN port mask: 1 = ports assigned to this VLAN
uint8_t fid; // Filtering Database Identifier
uint8_t prio; // VLAN priority
int has_prio; // priority defined;
int prio_override; // priority override (force per-VLAN priority)
int drop; // 1: drop the packet (VLAN not registered)
uint32_t port_mask; // VLAN port mask: 1 = ports assigned to this VLAN
uint8_t fid; // Filtering Database Identifier
uint8_t prio; // VLAN priority
int has_prio; // priority defined;
int prio_override; // priority override (force per-VLAN priority)
int drop; // 1: drop the packet (VLAN not registered)
};
/**
* \brief Copies src filtering entry body into dst filtering entry body.
* @return pointer to dst filtering entry.
*/
static inline
struct filtering_entry *rtu_fe_copy( struct filtering_entry *dst,
struct filtering_entry *src )
struct filtering_entry *rtu_fe_copy(struct filtering_entry *dst,
struct filtering_entry *src)
{
return memcpy( dst, src, sizeof(*src) );
return memcpy(dst, src, sizeof(*src));
}
/**
......@@ -177,19 +173,17 @@ struct filtering_entry *rtu_fe_copy( struct filtering_entry *dst,
* @param ent pointer to entry to clean (either in HCAM or HTAB)
* @return pointer to filtering entry that was cleaned
*/
static inline
struct filtering_entry *rtu_fe_clean(struct filtering_entry *ent)
static inline struct filtering_entry *rtu_fe_clean(struct filtering_entry *ent)
{
return memset( ent, 0, sizeof(*ent) );
return memset(ent, 0, sizeof(*ent));
}
/**
* \brief Returns number of seconds since the epoch.
*/
static inline
unsigned long now()
static inline unsigned long now()
{
return (unsigned long) time(NULL);
return (unsigned long)time(NULL);
}
int rtud_init_exports();
......
......@@ -42,7 +42,6 @@
#include <stdlib.h>
#include <sys/ioctl.h>
#include <switch_hw.h>
#include <hal_client.h>
......@@ -67,7 +66,7 @@ static uint32_t mac_entry_word4_w(struct filtering_entry *ent);
static int fd;
#define HAL_CONNECT_RETRIES 1000
#define HAL_CONNECT_TIMEOUT 2000000 /* us */
#define HAL_CONNECT_TIMEOUT 2000000 /* us */
/**
* \brief Initialize HW RTU memory map
......@@ -75,43 +74,40 @@ static int fd;
int rtu_init(void)
{
int err;
if(halexp_client_try_connect(HAL_CONNECT_RETRIES, HAL_CONNECT_TIMEOUT) < 0)
{
TRACE(
TRACE_FATAL,
"The HAL is not responding... Are you sure it's running on your switch?\n"
);
exit(-1);
}
int err;
// Used to 'get' RTU IRQs from kernel
if (halexp_client_try_connect(HAL_CONNECT_RETRIES, HAL_CONNECT_TIMEOUT)
< 0) {
TRACE(TRACE_FATAL,
"The HAL is not responding... Are you sure it's running on your switch?\n");
exit(-1);
}
// Used to 'get' RTU IRQs from kernel
fd = open(RTU_DEVNAME, O_RDWR);
if (fd < 0)
{
TRACE(TRACE_ERROR, "Can't open %s: is the RTU kernel driver loaded?", RTU_DEVNAME);
if (fd < 0) {
TRACE(TRACE_ERROR,
"Can't open %s: is the RTU kernel driver loaded?",
RTU_DEVNAME);
return errno;
}
// init IO memory map
err = shw_fpga_mmap_init();
if(err)
return err;
// init IO memory map
err = shw_fpga_mmap_init();
if (err)
return err;
TRACE(TRACE_INFO,"module initialized\n");
TRACE(TRACE_INFO, "module initialized\n");
return 0;
return 0;
}
void rtu_exit(void)
{
if(fd >= 0)
close(fd);
if (fd >= 0)
close(fd);
TRACE(TRACE_INFO, "module cleanup\n");
TRACE(TRACE_INFO, "module cleanup\n");
}
#define rtu_rd(reg) \
_fpga_readl(FPGA_BASE_RTU + offsetof(struct RTU_WB, reg))
......@@ -138,8 +134,8 @@ static inline uint32_t read_pcr(int port)
*/
int rtu_ufifo_is_empty(void)
{
uint32_t csr = rtu_rd( UFIFO_CSR);
return RTU_UFIFO_CSR_EMPTY & csr;
uint32_t csr = rtu_rd(UFIFO_CSR);
return RTU_UFIFO_CSR_EMPTY & csr;
}
/**
......@@ -148,10 +144,10 @@ int rtu_ufifo_is_empty(void)
*/
int rtu_read_learning_queue_cnt(void)
{
// Get counter from UFIFO Control-Status Register
// Fixme: USEDW returns 0 (FIFO overflow?)
uint32_t csr = rtu_rd( UFIFO_CSR);
return RTU_UFIFO_CSR_USEDW_R(csr);
// Get counter from UFIFO Control-Status Register
// Fixme: USEDW returns 0 (FIFO overflow?)
uint32_t csr = rtu_rd(UFIFO_CSR);
return RTU_UFIFO_CSR_USEDW_R(csr);
}
/**
......@@ -165,62 +161,58 @@ static int irq_disabled = 1;
int rtu_read_learning_queue(struct rtu_request *req)
{
int err;
if(irq_disabled)
{
ioctl(fd, WR_RTU_IRQENA);
irq_disabled = 0;
}
// If learning queue is empty, wait for UFIFO IRQ
if (rtu_ufifo_is_empty()) {
err = ioctl(fd, WR_RTU_IRQWAIT);
if (err && (err != -EAGAIN))
return err;
}
// read data from mapped IO memory
uint32_t r0 = rtu_rd( UFIFO_R0);
uint32_t r1 = rtu_rd( UFIFO_R1);
uint32_t r2 = rtu_rd( UFIFO_R2);
uint32_t r3 = rtu_rd( UFIFO_R3);
uint32_t r4 = rtu_rd( UFIFO_R4);
// Once read: if learning queue becomes empty again, enable UFIFO IRQ
// unmarshall data and populate request
uint32_t dmac_lo = RTU_UFIFO_R0_DMAC_LO_R(r0);
uint32_t dmac_hi = RTU_UFIFO_R1_DMAC_HI_R(r1);
uint32_t smac_lo = RTU_UFIFO_R2_SMAC_LO_R(r2);
uint32_t smac_hi = RTU_UFIFO_R3_SMAC_HI_R(r3);
req->port_id = RTU_UFIFO_R4_PID_R(r4);
req->has_prio = RTU_UFIFO_R4_HAS_PRIO & r4;
req->prio = RTU_UFIFO_R4_PRIO_R(r4);
req->has_vid = RTU_UFIFO_R4_HAS_VID & r4;
req->vid = RTU_UFIFO_R4_VID_R(r4);
// destination mac
req->dst[5] = 0xFF & dmac_lo;
req->dst[4] = 0xFF & (dmac_lo >> 8);
req->dst[3] = 0xFF & (dmac_lo >> 16);
req->dst[2] = 0xFF & (dmac_lo >> 24);
req->dst[1] = 0xFF & dmac_hi;
req->dst[0] = 0xFF & (dmac_hi >> 8);
// source mac
req->src[5] = 0xFF & smac_lo;
req->src[4] = 0xFF & (smac_lo >> 8);
req->src[3] = 0xFF & (smac_lo >> 16);
req->src[2] = 0xFF & (smac_lo >> 24);
req->src[1] = 0xFF & smac_hi;
req->src[0] = 0xFF & (smac_hi >> 8);
ioctl(fd, WR_RTU_IRQENA);
return 0;
}
int err;
if (irq_disabled) {
ioctl(fd, WR_RTU_IRQENA);
irq_disabled = 0;
}
// If learning queue is empty, wait for UFIFO IRQ
if (rtu_ufifo_is_empty()) {
err = ioctl(fd, WR_RTU_IRQWAIT);
if (err && (err != -EAGAIN))
return err;
}
// read data from mapped IO memory
uint32_t r0 = rtu_rd(UFIFO_R0);
uint32_t r1 = rtu_rd(UFIFO_R1);
uint32_t r2 = rtu_rd(UFIFO_R2);
uint32_t r3 = rtu_rd(UFIFO_R3);
uint32_t r4 = rtu_rd(UFIFO_R4);
// Once read: if learning queue becomes empty again, enable UFIFO IRQ
// unmarshall data and populate request
uint32_t dmac_lo = RTU_UFIFO_R0_DMAC_LO_R(r0);
uint32_t dmac_hi = RTU_UFIFO_R1_DMAC_HI_R(r1);
uint32_t smac_lo = RTU_UFIFO_R2_SMAC_LO_R(r2);
uint32_t smac_hi = RTU_UFIFO_R3_SMAC_HI_R(r3);
req->port_id = RTU_UFIFO_R4_PID_R(r4);
req->has_prio = RTU_UFIFO_R4_HAS_PRIO & r4;
req->prio = RTU_UFIFO_R4_PRIO_R(r4);
req->has_vid = RTU_UFIFO_R4_HAS_VID & r4;
req->vid = RTU_UFIFO_R4_VID_R(r4);
// destination mac
req->dst[5] = 0xFF & dmac_lo;
req->dst[4] = 0xFF & (dmac_lo >> 8);
req->dst[3] = 0xFF & (dmac_lo >> 16);
req->dst[2] = 0xFF & (dmac_lo >> 24);
req->dst[1] = 0xFF & dmac_hi;
req->dst[0] = 0xFF & (dmac_hi >> 8);
// source mac
req->src[5] = 0xFF & smac_lo;
req->src[4] = 0xFF & (smac_lo >> 8);
req->src[3] = 0xFF & (smac_lo >> 16);
req->src[2] = 0xFF & (smac_lo >> 24);
req->src[1] = 0xFF & smac_hi;
req->src[0] = 0xFF & (smac_hi >> 8);
ioctl(fd, WR_RTU_IRQENA);
return 0;
}
// MFIFO -> HTAB
......@@ -230,9 +222,9 @@ int rtu_read_learning_queue(struct rtu_request *req)
*/
int rtu_read_mfifo_cnt(void)
{
// Get counter from MFIFO Control-Status Register
uint32_t csr = rtu_rd( MFIFO_CSR);
return RTU_MFIFO_CSR_USEDW_R(csr);
// Get counter from MFIFO Control-Status Register
uint32_t csr = rtu_rd(MFIFO_CSR);
return RTU_MFIFO_CSR_USEDW_R(csr);
}
/**
......@@ -241,8 +233,8 @@ int rtu_read_mfifo_cnt(void)
*/
int rtu_mfifo_is_full(void)
{
uint32_t csr = rtu_rd( MFIFO_CSR);
return RTU_MFIFO_CSR_FULL & csr;
uint32_t csr = rtu_rd(MFIFO_CSR);
return RTU_MFIFO_CSR_FULL & csr;
}
/**
......@@ -251,16 +243,16 @@ int rtu_mfifo_is_full(void)
*/
int rtu_mfifo_is_empty(void)
{
uint32_t csr = rtu_rd( MFIFO_CSR);
return RTU_MFIFO_CSR_EMPTY & csr;
uint32_t csr = rtu_rd(MFIFO_CSR);
return RTU_MFIFO_CSR_EMPTY & csr;
}
static void flush_mfifo()
{
uint32_t gcr = rtu_rd (GCR);
uint32_t gcr = rtu_rd(GCR);
rtu_wr(GCR, gcr | RTU_GCR_MFIFOTRIG);
while(!rtu_rd(GCR) & RTU_GCR_MFIFOTRIG); /* wait while the RTU is busy flushing the MFIFO */
while (!rtu_rd(GCR) & RTU_GCR_MFIFOTRIG) ; /* wait while the RTU is busy flushing the MFIFO */
}
/**
......@@ -268,28 +260,27 @@ static void flush_mfifo()
* @param ent MAC table entry to be written to MFIFO.
* @param zbt_addr ZBT SRAM memory address in which MAC entry shoud be added.
*/
void rtu_write_htab_entry(uint16_t zbt_addr, struct filtering_entry *ent, int flush)
{
write_mfifo_addr(zbt_addr);
write_mfifo_data(mac_entry_word0_w(ent));
write_mfifo_data(mac_entry_word1_w(ent));
write_mfifo_data(mac_entry_word2_w(ent));
write_mfifo_data(mac_entry_word3_w(ent));
write_mfifo_data(mac_entry_word4_w(ent));
if(flush)
flush_mfifo();
TRACE_DBG(
TRACE_INFO,
"write htab entry [with flush]: addr %x ent %08x %08x %08x %08x %08x",
zbt_addr,
mac_entry_word0_w(ent),
mac_entry_word1_w(ent),
mac_entry_word2_w(ent),
mac_entry_word3_w(ent),
mac_entry_word4_w(ent)
);
void rtu_write_htab_entry(uint16_t zbt_addr, struct filtering_entry *ent,
int flush)
{
write_mfifo_addr(zbt_addr);
write_mfifo_data(mac_entry_word0_w(ent));
write_mfifo_data(mac_entry_word1_w(ent));
write_mfifo_data(mac_entry_word2_w(ent));
write_mfifo_data(mac_entry_word3_w(ent));
write_mfifo_data(mac_entry_word4_w(ent));
if (flush)
flush_mfifo();
TRACE_DBG(TRACE_INFO,
"write htab entry [with flush]: addr %x ent %08x %08x %08x %08x %08x",
zbt_addr,
mac_entry_word0_w(ent),
mac_entry_word1_w(ent),
mac_entry_word2_w(ent),
mac_entry_word3_w(ent), mac_entry_word4_w(ent)
);
}
/**
......@@ -298,19 +289,18 @@ void rtu_write_htab_entry(uint16_t zbt_addr, struct filtering_entry *ent, int fl
*/
void rtu_clean_htab(void)
{
int addr;
for (addr = 0; addr < RTU_ENTRIES; addr++) {
write_mfifo_addr(addr * 8);
write_mfifo_data(0x00000000);
write_mfifo_data(0x00000000);
write_mfifo_data(0x00000000);
write_mfifo_data(0x00000000);
write_mfifo_data(0x00000000);
int addr;
for (addr = 0; addr < RTU_ENTRIES; addr++) {
write_mfifo_addr(addr * 8);
write_mfifo_data(0x00000000);
write_mfifo_data(0x00000000);
write_mfifo_data(0x00000000);
write_mfifo_data(0x00000000);
write_mfifo_data(0x00000000);
flush_mfifo();
}
}
}
// AGING RAM - HTAB
/**
......@@ -318,13 +308,12 @@ void rtu_clean_htab(void)
* Aging RAM Size: 256 32-bit words
*/
void rtu_read_aging_bitmap( uint32_t *bitmap )
void rtu_read_aging_bitmap(uint32_t * bitmap)
{
int i;
for(i=0; i< RTU_ENTRIES / 32; i++)
{
bitmap[i] = _fpga_readl(FPGA_BASE_RTU + RTU_ARAM_BASE + 4*i);
_fpga_writel(FPGA_BASE_RTU + RTU_ARAM_BASE + 4*i, 0);
for (i = 0; i < RTU_ENTRIES / 32; i++) {
bitmap[i] = _fpga_readl(FPGA_BASE_RTU + RTU_ARAM_BASE + 4 * i);
_fpga_writel(FPGA_BASE_RTU + RTU_ARAM_BASE + 4 * i, 0);
}
}
......@@ -337,27 +326,24 @@ void rtu_read_aging_bitmap( uint32_t *bitmap )
*/
void rtu_write_vlan_entry(int vid, struct vlan_table_entry *ent)
{
uint32_t vtr1=0, vtr2=0;
uint32_t vtr1 = 0, vtr2 = 0;
vtr2 = ent->port_mask;
vtr1 = RTU_VTR1_UPDATE
| RTU_VTR1_VID_W(vid)
| (ent->drop ? RTU_VTR1_DROP : 0)
| (ent->prio_override ? RTU_VTR1_PRIO_OVERRIDE : 0)
| (ent->has_prio ? RTU_VTR1_HAS_PRIO : 0)
| RTU_VTR1_PRIO_W(ent->prio)
| RTU_VTR1_FID_W(ent->fid);
vtr2 = ent->port_mask;
vtr1 = RTU_VTR1_UPDATE | RTU_VTR1_VID_W(vid)
| (ent->drop ? RTU_VTR1_DROP : 0)
| (ent->prio_override ? RTU_VTR1_PRIO_OVERRIDE : 0)
| (ent->has_prio ? RTU_VTR1_HAS_PRIO : 0)
| RTU_VTR1_PRIO_W(ent->prio)
| RTU_VTR1_FID_W(ent->fid);
rtu_wr(VTR2, vtr2);
rtu_wr(VTR1, vtr1);
rtu_wr(VTR2, vtr2);
rtu_wr(VTR1, vtr1);
if(ent->drop > 0 && ent->port_mask == 0x0)
{
TRACE(TRACE_INFO, "RemoveVlan: vid %d (fid %d)", vid, ent->fid);
}
else
{
TRACE(TRACE_INFO, "AddVlan: vid %d (fid %d) port_mask 0x%x", vid, ent->fid, ent->port_mask);
if (ent->drop > 0 && ent->port_mask == 0x0) {
TRACE(TRACE_INFO, "RemoveVlan: vid %d (fid %d)", vid, ent->fid);
} else {
TRACE(TRACE_INFO, "AddVlan: vid %d (fid %d) port_mask 0x%x",
vid, ent->fid, ent->port_mask);
}
}
......@@ -366,15 +352,15 @@ void rtu_write_vlan_entry(int vid, struct vlan_table_entry *ent)
* \brief Cleans VLAN entry in VLAN table
* @param addr memory address which shoud be cleaned.
*/
void rtu_clean_vlan_entry( int vid )
void rtu_clean_vlan_entry(int vid)
{
uint32_t vtr1=0, vtr2=0;
uint32_t vtr1 = 0, vtr2 = 0;
vtr2 = 0;
vtr1 = RTU_VTR1_UPDATE | RTU_VTR1_VID_W(vid);
vtr2 = 0;
vtr1 = RTU_VTR1_UPDATE | RTU_VTR1_VID_W(vid);
rtu_wr(VTR2, vtr2);
rtu_wr(VTR1, vtr1);
rtu_wr(VTR2, vtr2);
rtu_wr(VTR1, vtr1);
}
/**
......@@ -382,12 +368,11 @@ void rtu_clean_vlan_entry( int vid )
*/
void rtu_clean_vlan(void)
{
int addr;
for (addr = 0; addr < NUM_VLANS; addr++)
rtu_clean_vlan_entry(addr);
int addr;
for (addr = 0; addr < NUM_VLANS; addr++)
rtu_clean_vlan_entry(addr);
}
// RTU Global Control Register
/**
......@@ -395,9 +380,9 @@ void rtu_clean_vlan(void)
*/
void rtu_enable(void)
{
uint32_t gcr = rtu_rd( GCR);
uint32_t gcr = rtu_rd(GCR);
rtu_wr(GCR, gcr | RTU_GCR_G_ENA);
TRACE_DBG(TRACE_INFO,"updated gcr (enable): %x\n", gcr);
TRACE_DBG(TRACE_INFO, "updated gcr (enable): %x\n", gcr);
}
/**
......@@ -405,9 +390,9 @@ void rtu_enable(void)
*/
void rtu_disable(void)
{
uint32_t gcr = rtu_rd( GCR);
uint32_t gcr = rtu_rd(GCR);
rtu_wr(GCR, gcr & (~RTU_GCR_G_ENA));
TRACE_DBG(TRACE_INFO,"updated gcr (disable): %x\n", gcr);
TRACE_DBG(TRACE_INFO, "updated gcr (disable): %x\n", gcr);
}
/**
......@@ -416,8 +401,8 @@ void rtu_disable(void)
*/
uint16_t rtu_read_hash_poly(void)
{
uint32_t gcr = rtu_rd( GCR);
return RTU_GCR_POLY_VAL_R(gcr);
uint32_t gcr = rtu_rd(GCR);
return RTU_GCR_POLY_VAL_R(gcr);
}
/**
......@@ -426,16 +411,15 @@ uint16_t rtu_read_hash_poly(void)
*/
void rtu_write_hash_poly(uint16_t hash_poly)
{
// Get current GCR
uint32_t gcr = rtu_rd( GCR);
// Clear previous hash poly and insert the new one
gcr = (gcr & (~RTU_GCR_POLY_VAL_MASK)) | RTU_GCR_POLY_VAL_W(hash_poly);
// Update GCR
rtu_wr(GCR, gcr );
TRACE_DBG(TRACE_INFO,"updated gcr (poly): %x\n", gcr);
// Get current GCR
uint32_t gcr = rtu_rd(GCR);
// Clear previous hash poly and insert the new one
gcr = (gcr & (~RTU_GCR_POLY_VAL_MASK)) | RTU_GCR_POLY_VAL_W(hash_poly);
// Update GCR
rtu_wr(GCR, gcr);
TRACE_DBG(TRACE_INFO, "updated gcr (poly): %x\n", gcr);
}
// PORT SETTINGS
/**
......@@ -447,8 +431,8 @@ void rtu_write_hash_poly(uint16_t hash_poly)
*/
int rtu_set_fixed_prio_on_port(int port, uint8_t prio)
{
if( (port < MIN_PORT) || (port > MAX_PORT) )
return -EINVAL;
if ((port < MIN_PORT) || (port > MAX_PORT))
return -EINVAL;
uint32_t pcr = read_pcr(port);
write_pcr(port, pcr | RTU_PCR_FIX_PRIO | RTU_PCR_PRIO_VAL_W(prio));
......@@ -463,11 +447,13 @@ int rtu_set_fixed_prio_on_port(int port, uint8_t prio)
*/
int rtu_unset_fixed_prio_on_port(int port)
{
if( (port < MIN_PORT) || (port > MAX_PORT) )
return -EINVAL;
if ((port < MIN_PORT) || (port > MAX_PORT))
return -EINVAL;
uint32_t pcr = read_pcr(port);
write_pcr(port, pcr & (RTU_PCR_LEARN_EN | RTU_PCR_PASS_ALL | RTU_PCR_PASS_BPDU | RTU_PCR_B_UNREC));
write_pcr(port,
pcr & (RTU_PCR_LEARN_EN | RTU_PCR_PASS_ALL | RTU_PCR_PASS_BPDU
| RTU_PCR_B_UNREC));
return 0;
}
......@@ -480,16 +466,14 @@ int rtu_unset_fixed_prio_on_port(int port)
*/
int rtu_learn_enable_on_port(int port, int flag)
{
if( (port < MIN_PORT) || (port > MAX_PORT) )
return -EINVAL;
if ((port < MIN_PORT) || (port > MAX_PORT))
return -EINVAL;
uint32_t pcr = read_pcr(port);
pcr = flag ?
RTU_PCR_LEARN_EN | pcr :
(~RTU_PCR_LEARN_EN) & pcr ;
pcr = flag ? RTU_PCR_LEARN_EN | pcr : (~RTU_PCR_LEARN_EN) & pcr;
write_pcr(port, pcr);
return 0;
return 0;
}
/**
......@@ -501,15 +485,13 @@ int rtu_learn_enable_on_port(int port, int flag)
*/
int rtu_pass_bpdu_on_port(int port, int flag)
{
if( (port < MIN_PORT) || (port > MAX_PORT) )
return -EINVAL;
if ((port < MIN_PORT) || (port > MAX_PORT))
return -EINVAL;
uint32_t pcr = read_pcr(port);
pcr = flag ?
RTU_PCR_PASS_BPDU | pcr :
(~RTU_PCR_PASS_BPDU) & pcr ;
pcr = flag ? RTU_PCR_PASS_BPDU | pcr : (~RTU_PCR_PASS_BPDU) & pcr;
write_pcr(port, pcr);
return 0;
return 0;
}
/**
......@@ -520,16 +502,14 @@ int rtu_pass_bpdu_on_port(int port, int flag)
*/
int rtu_pass_all_on_port(int port, int flag)
{
if( (port < MIN_PORT) || (port > MAX_PORT) )
return -EINVAL;
if ((port < MIN_PORT) || (port > MAX_PORT))
return -EINVAL;
uint32_t pcr = read_pcr(port);
pcr = flag ?
RTU_PCR_PASS_ALL | pcr :
(~RTU_PCR_PASS_ALL) & pcr ;
pcr = flag ? RTU_PCR_PASS_ALL | pcr : (~RTU_PCR_PASS_ALL) & pcr;
write_pcr(port, pcr);
return 0;
return 0;
}
/**
......@@ -540,20 +520,17 @@ int rtu_pass_all_on_port(int port, int flag)
*/
int rtu_set_unrecognised_behaviour_on_port(int port, int flag)
{
if( (port < MIN_PORT) || (port > MAX_PORT) )
return -EINVAL;
if ((port < MIN_PORT) || (port > MAX_PORT))
return -EINVAL;
uint32_t pcr = read_pcr(port);
pcr = flag ?
RTU_PCR_B_UNREC | pcr :
(~RTU_PCR_B_UNREC) & pcr ;
pcr = flag ? RTU_PCR_B_UNREC | pcr : (~RTU_PCR_B_UNREC) & pcr;
write_pcr(port, pcr);
return 0;
return 0;
}
//---------------------------------------------
// Private Methods
//---------------------------------------------
......@@ -562,64 +539,59 @@ int rtu_set_unrecognised_behaviour_on_port(int port, int flag)
static void write_mfifo_addr(uint32_t zbt_addr)
{
rtu_wr(MFIFO_R0, RTU_MFIFO_R0_AD_SEL);
rtu_wr(MFIFO_R1, zbt_addr);
rtu_wr(MFIFO_R0, RTU_MFIFO_R0_AD_SEL);
rtu_wr(MFIFO_R1, zbt_addr);
}
static void write_mfifo_data(uint32_t word)
{
rtu_wr(MFIFO_R0, RTU_MFIFO_R0_DATA_SEL);
rtu_wr(MFIFO_R1, word);
rtu_wr(MFIFO_R0, RTU_MFIFO_R0_DATA_SEL);
rtu_wr(MFIFO_R1, word);
}
// to marshall MAC entries
static uint32_t mac_entry_word0_w(struct filtering_entry *ent)
{
return
((0xFF & ent->mac[0]) << 24) |
((0xFF & ent->mac[1]) << 16) |
((0xFF & ent->fid) << 4) |
((0x1 & ent->is_bpdu) << 2) |
((0x1 & ent->end_of_bucket) << 1) |
((0x1 & ent->valid ) ) ;
return
((0xFF & ent->mac[0]) << 24) |
((0xFF & ent->mac[1]) << 16) |
((0xFF & ent->fid) << 4) |
((0x1 & ent->is_bpdu) << 2) |
((0x1 & ent->end_of_bucket) << 1) | ((0x1 & ent->valid));
}
static uint32_t mac_entry_word1_w(struct filtering_entry *ent)
{
return
((0xFF & ent->mac[2]) << 24) |
((0xFF & ent->mac[3]) << 16) |
((0xFF & ent->mac[4]) << 8) |
((0xFF & ent->mac[5]) ) ;
return
((0xFF & ent->mac[2]) << 24) |
((0xFF & ent->mac[3]) << 16) |
((0xFF & ent->mac[4]) << 8) | ((0xFF & ent->mac[5]));
}
static uint32_t mac_entry_word2_w(struct filtering_entry *ent)
{
return
((0x1 & ent->drop_when_dest) << 28) |
((0x1 & ent->prio_override_dst) << 27) |
((0x7 & ent->prio_dst) << 24) |
((0x1 & ent->has_prio_dst) << 23) |
((0x1 & ent->drop_unmatched_src_ports) << 22) |
((0x1 & ent->drop_when_source) << 21) |
((0x1 & ent->prio_override_src) << 20) |
((0x7 & ent->prio_src) << 17) |
((0x1 & ent->has_prio_src) << 16);
return
((0x1 & ent->drop_when_dest) << 28) |
((0x1 & ent->prio_override_dst) << 27) |
((0x7 & ent->prio_dst) << 24) |
((0x1 & ent->has_prio_dst) << 23) |
((0x1 & ent->drop_unmatched_src_ports) << 22) |
((0x1 & ent->drop_when_source) << 21) |
((0x1 & ent->prio_override_src) << 20) |
((0x7 & ent->prio_src) << 17) | ((0x1 & ent->has_prio_src) << 16);
}
static uint32_t mac_entry_word3_w(struct filtering_entry *ent)
{
return
((0xFFFF & ent->port_mask_dst) << 16) |
((0xFFFF & ent->port_mask_src) ) ;
return
((0xFFFF & ent->port_mask_dst) << 16) |
((0xFFFF & ent->port_mask_src));
}
static uint32_t mac_entry_word4_w(struct filtering_entry *ent)
{
return
((0xFFFF & (ent->port_mask_dst >> 16)) << 16) |
((0xFFFF & (ent->port_mask_src >> 16)) ) ;
return
((0xFFFF & (ent->port_mask_dst >> 16)) << 16) |
((0xFFFF & (ent->port_mask_src >> 16)));
}
......@@ -27,7 +27,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WHITERABBIT_RTU_DRV_H
#define __WHITERABBIT_RTU_DRV_H
......@@ -39,7 +38,7 @@
#define RTU_DEVNAME "/dev/wr_rtu"
int rtu_init(void)
__attribute__((warn_unused_result));
__attribute__ ((warn_unused_result));
void rtu_exit(void);
// UFIFO
......@@ -50,12 +49,13 @@ int rtu_read_learning_queue(struct rtu_request *req);
// HTAB access
void rtu_write_htab_entry(uint16_t zbt_addr, struct filtering_entry *ent, int flush);
void rtu_write_htab_entry(uint16_t zbt_addr, struct filtering_entry *ent,
int flush);
void rtu_clean_htab(void);
// AGING - HTAB
void rtu_read_aging_bitmap(uint32_t *bitmap);
void rtu_read_aging_bitmap(uint32_t * bitmap);
// VLAN TABLE
......@@ -76,17 +76,17 @@ void rtu_set_active_bank(uint8_t bank);
// PORT SETTINGS
int rtu_set_fixed_prio_on_port(int port, uint8_t prio)
__attribute__((warn_unused_result));
__attribute__ ((warn_unused_result));
int rtu_unset_fixed_prio_on_port(int port)
__attribute__((warn_unused_result));
__attribute__ ((warn_unused_result));
int rtu_learn_enable_on_port(int port, int flag)
__attribute__((warn_unused_result));
__attribute__ ((warn_unused_result));
int rtu_pass_bpdu_on_port(int port, int flag)
__attribute__((warn_unused_result));
__attribute__ ((warn_unused_result));
int rtu_pass_all_on_port(int port, int pass_all)
__attribute__((warn_unused_result));
__attribute__ ((warn_unused_result));
int rtu_set_unrecognised_behaviour_on_port(int port, int flag)
__attribute__((warn_unused_result));
__attribute__ ((warn_unused_result));
// IRQs
......@@ -94,5 +94,4 @@ void rtu_enable_irq(void);
void rtu_disable_irq(void);
void rtu_clear_irq(void);
#endif /*__WHITERABBIT_RTU_DRV_H*/
......@@ -30,7 +30,6 @@
#include <stdlib.h>
#include <sys/ioctl.h>
#include <switch_hw.h>
#include <hal_client.h>
......@@ -40,20 +39,19 @@
#include "rtu_ext_drv.h"
#include "wr_rtu.h"
int rtux_init(void)
{
rtux_set_hp_prio_mask (0x00/*hp prio mask*/); // no HP
rtux_set_hp_prio_mask(0x00 /*hp prio mask */ ); // no HP
rtux_set_feature_ctrl (0 /*mr*/,
1 /*mac_ptp*/,
1 /*mac_ll*/,
0 /*mac_single*/,
0 /*mac_range*/,
1 /*mac_br*/,
0 /*drop when full_match full*/);
rtux_set_feature_ctrl(0 /*mr */ ,
1 /*mac_ptp */ ,
1 /*mac_ll */ ,
0 /*mac_single */ ,
0 /*mac_range */ ,
1 /*mac_br */ ,
0 /*drop when full_match full */ );
return 0;
return 0;
}
#define rtu_rd(reg) \
......@@ -62,22 +60,19 @@ int rtux_init(void)
#define rtu_wr(reg, val) \
_fpga_writel(FPGA_BASE_RTU + offsetof(struct RTU_WB, reg), val)
static uint32_t get_mac_lo(uint8_t mac[ETH_ALEN])
{
return
((0xFF & mac[2]) << 24) |
((0xFF & mac[3]) << 16) |
((0xFF & mac[4]) << 8) |
((0xFF & mac[5]) ) ;
return
((0xFF & mac[2]) << 24) |
((0xFF & mac[3]) << 16) |
((0xFF & mac[4]) << 8) | ((0xFF & mac[5]));
}
static uint32_t get_mac_hi(uint8_t mac[ETH_ALEN])
{
return
((0xFF & mac[0]) << 8) |
((0xFF & mac[1]) ) ;
return ((0xFF & mac[0]) << 8) | ((0xFF & mac[1]));
}
/**
* \brief Configures a single MACs to be forwarded using fast-match (broadcast within VLAN)
* @param mac_id ID of the entry
......@@ -86,20 +81,21 @@ static uint32_t get_mac_hi(uint8_t mac[ETH_ALEN])
*/
void rtux_add_ff_mac_single(int mac_id, int valid, uint8_t mac[ETH_ALEN])
{
uint32_t mac_hi=0, mac_lo=0;
mac_lo = RTU_RX_FF_MAC_R0_LO_W (get_mac_lo(mac)) ;
mac_hi = RTU_RX_FF_MAC_R1_HI_ID_W (get_mac_hi(mac)) |
RTU_RX_FF_MAC_R1_ID_W (mac_id) |
0 | // type = 0
RTU_RX_FF_MAC_R1_VALID;
rtu_wr(RX_FF_MAC_R0, mac_lo);
rtu_wr(RX_FF_MAC_R1, mac_hi);
TRACE(TRACE_INFO,"RTU eXtension: set fast forward single mac (id=%d, valid=%d) of "
"%x:%x:%x:%x:%x:%x", mac_id, valid,mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
uint32_t mac_hi = 0, mac_lo = 0;
mac_lo = RTU_RX_FF_MAC_R0_LO_W(get_mac_lo(mac));
mac_hi = RTU_RX_FF_MAC_R1_HI_ID_W(get_mac_hi(mac)) | RTU_RX_FF_MAC_R1_ID_W(mac_id) | 0 | // type = 0
RTU_RX_FF_MAC_R1_VALID;
rtu_wr(RX_FF_MAC_R0, mac_lo);
rtu_wr(RX_FF_MAC_R1, mac_hi);
TRACE(TRACE_INFO,
"RTU eXtension: set fast forward single mac (id=%d, valid=%d) of "
"%x:%x:%x:%x:%x:%x", mac_id, valid, mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
}
/**
* \brief Configures a range of MACs to be forwarded using fast-match (broadcast within VLAN)
* @param mac_id ID of the entry
......@@ -108,42 +104,40 @@ void rtux_add_ff_mac_single(int mac_id, int valid, uint8_t mac[ETH_ALEN])
* @param mac_upper MAC with address that finishes the range
*/
void rtux_add_ff_mac_range(int mac_id, int valid, uint8_t mac_lower[ETH_ALEN],
uint8_t mac_upper[ETH_ALEN])
uint8_t mac_upper[ETH_ALEN])
{
uint32_t mac_hi=0, mac_lo=0;
uint32_t m_mac_id=0; // modified mac id
// writting lower boundary of the mac range
m_mac_id = (~(1 << 7) ) & mac_id; // lower range (highest bit is low)
mac_lo = RTU_RX_FF_MAC_R0_LO_W (get_mac_lo(mac_lower)) ;
mac_hi = RTU_RX_FF_MAC_R1_HI_ID_W (get_mac_hi(mac_lower)) |
RTU_RX_FF_MAC_R1_ID_W (m_mac_id) |
RTU_RX_FF_MAC_R1_TYPE | // type = 1
RTU_RX_FF_MAC_R1_VALID;
rtu_wr(RX_FF_MAC_R0, mac_lo);
rtu_wr(RX_FF_MAC_R1, mac_hi);
// writting upper boundary of the mac range
m_mac_id = (1 << 7) | mac_id; // upper range high (highest bit is high)
mac_lo = RTU_RX_FF_MAC_R0_LO_W (get_mac_lo(mac_upper)) ;
mac_hi = RTU_RX_FF_MAC_R1_HI_ID_W (get_mac_hi(mac_upper)) |
RTU_RX_FF_MAC_R1_ID_W (m_mac_id) |
RTU_RX_FF_MAC_R1_TYPE | // type = 1
RTU_RX_FF_MAC_R1_VALID;
rtu_wr(RX_FF_MAC_R0, mac_lo);
rtu_wr(RX_FF_MAC_R1, mac_hi);
TRACE(TRACE_INFO,"RTU eXtension: set fast forward mac range: (id=%d, valid=%d):", mac_id,
valid);
TRACE(TRACE_INFO,"\t lower_mac = %x:%x:%x:%x:%x:%x",mac_lower[0],mac_lower[1],mac_lower[2],
mac_lower[3],mac_lower[4],mac_lower[5]);
TRACE(TRACE_INFO,"\t upper_mac = %x:%x:%x:%x:%x:%x",mac_upper[0],mac_upper[1],mac_upper[2],
mac_upper[3],mac_upper[4],mac_upper[5]);
uint32_t mac_hi = 0, mac_lo = 0;
uint32_t m_mac_id = 0; // modified mac id
// writting lower boundary of the mac range
m_mac_id = (~(1 << 7)) & mac_id; // lower range (highest bit is low)
mac_lo = RTU_RX_FF_MAC_R0_LO_W(get_mac_lo(mac_lower));
mac_hi = RTU_RX_FF_MAC_R1_HI_ID_W(get_mac_hi(mac_lower)) | RTU_RX_FF_MAC_R1_ID_W(m_mac_id) | RTU_RX_FF_MAC_R1_TYPE | // type = 1
RTU_RX_FF_MAC_R1_VALID;
rtu_wr(RX_FF_MAC_R0, mac_lo);
rtu_wr(RX_FF_MAC_R1, mac_hi);
// writting upper boundary of the mac range
m_mac_id = (1 << 7) | mac_id; // upper range high (highest bit is high)
mac_lo = RTU_RX_FF_MAC_R0_LO_W(get_mac_lo(mac_upper));
mac_hi = RTU_RX_FF_MAC_R1_HI_ID_W(get_mac_hi(mac_upper)) | RTU_RX_FF_MAC_R1_ID_W(m_mac_id) | RTU_RX_FF_MAC_R1_TYPE | // type = 1
RTU_RX_FF_MAC_R1_VALID;
rtu_wr(RX_FF_MAC_R0, mac_lo);
rtu_wr(RX_FF_MAC_R1, mac_hi);
TRACE(TRACE_INFO,
"RTU eXtension: set fast forward mac range: (id=%d, valid=%d):",
mac_id, valid);
TRACE(TRACE_INFO, "\t lower_mac = %x:%x:%x:%x:%x:%x", mac_lower[0],
mac_lower[1], mac_lower[2], mac_lower[3], mac_lower[4],
mac_lower[5]);
TRACE(TRACE_INFO, "\t upper_mac = %x:%x:%x:%x:%x:%x", mac_upper[0],
mac_upper[1], mac_upper[2], mac_upper[3], mac_upper[4],
mac_upper[5]);
}
/**
......@@ -153,41 +147,49 @@ void rtux_add_ff_mac_range(int mac_id, int valid, uint8_t mac_lower[ETH_ALEN],
* @param rx indicates that traffic received to src port should be mirrored
* @param tx indicates that traffic transmitted to src port should be mirrored
*/
void rtux_set_port_mirror(uint32_t mirror_src_mask, uint32_t mirror_dst_mask, int rx, int tx)
void rtux_set_port_mirror(uint32_t mirror_src_mask, uint32_t mirror_dst_mask,
int rx, int tx)
{
uint32_t mp_src_rx=0, mp_src_tx=0, mp_dst=0, mp_sel=0;
mp_dst = RTU_RX_MP_R1_MASK_W(mirror_dst_mask);
mp_src_tx = 0;
mp_src_rx = 0;
mp_sel = 0 ; // destinatioon (dst_src=0)
rtu_wr(RX_MP_R0,mp_sel);
rtu_wr(RX_MP_R1,mp_dst);
if(rx)
mp_src_rx = RTU_RX_MP_R1_MASK_W(mirror_src_mask);
else
mp_src_rx = 0;
mp_sel = 0;
mp_sel = RTU_RX_MP_R0_DST_SRC; // source (dst_src=1), reception traffic (rx_tx=0)
rtu_wr(RX_MP_R0,mp_sel);
rtu_wr(RX_MP_R1,mp_src_rx);
if(tx)
mp_src_tx = RTU_RX_MP_R1_MASK_W(mirror_src_mask);
else
mp_src_tx = 0;
mp_sel = 0;
mp_sel = RTU_RX_MP_R0_DST_SRC | RTU_RX_MP_R0_RX_TX;
// source (dst_src=1), transmission traffic (rx_tx=1)
rtu_wr(RX_MP_R0,mp_sel);
rtu_wr(RX_MP_R1,mp_src_tx);
TRACE(TRACE_INFO,"\t mirror output port(s) mask (dst) = 0x%x",mp_dst);
TRACE(TRACE_INFO,"\t ingress traffic mirror source port(s) mask (src_rx) = 0x%x",mp_src_rx);
TRACE(TRACE_INFO,"\t egress traffic mirror source port(s) mask (src_tx) = 0x%x",mp_src_tx);
uint32_t mp_src_rx = 0, mp_src_tx = 0, mp_dst = 0, mp_sel = 0;
mp_dst = RTU_RX_MP_R1_MASK_W(mirror_dst_mask);
mp_src_tx = 0;
mp_src_rx = 0;
mp_sel = 0; // destinatioon (dst_src=0)
rtu_wr(RX_MP_R0, mp_sel);
rtu_wr(RX_MP_R1, mp_dst);
if (rx)
mp_src_rx = RTU_RX_MP_R1_MASK_W(mirror_src_mask);
else
mp_src_rx = 0;
mp_sel = 0;
mp_sel = RTU_RX_MP_R0_DST_SRC; // source (dst_src=1), reception traffic (rx_tx=0)
rtu_wr(RX_MP_R0, mp_sel);
rtu_wr(RX_MP_R1, mp_src_rx);
if (tx)
mp_src_tx = RTU_RX_MP_R1_MASK_W(mirror_src_mask);
else
mp_src_tx = 0;
mp_sel = 0;
mp_sel = RTU_RX_MP_R0_DST_SRC | RTU_RX_MP_R0_RX_TX;
// source (dst_src=1), transmission traffic (rx_tx=1)
rtu_wr(RX_MP_R0, mp_sel);
rtu_wr(RX_MP_R1, mp_src_tx);
TRACE(TRACE_INFO,
"\t mirror output port(s) mask (dst) = 0x%x",
mp_dst);
TRACE(TRACE_INFO,
"\t ingress traffic mirror source port(s) mask (src_rx) = 0x%x",
mp_src_rx);
TRACE(TRACE_INFO,
"\t egress traffic mirror source port(s) mask (src_tx) = 0x%x",
mp_src_tx);
}
/**
* \brief Read the mask which which priorities are considered High Priority (this only
* concerns the traffic which is fast-forwarded)
......@@ -196,13 +198,15 @@ void rtux_set_port_mirror(uint32_t mirror_src_mask, uint32_t mirror_dst_mask, in
*/
uint8_t rtux_get_hp_prio_mask()
{
uint32_t val=0;
uint32_t val = 0;
val = rtu_rd(RX_CTR);
TRACE(TRACE_INFO,"RTU eXtension: read hp priorities (for which priorities traffic is "
"considered HP), mask[rd]=0x%x",RTU_RX_CTR_PRIO_MASK_R(val) );
return (uint8_t)RTU_RX_CTR_PRIO_MASK_R(val);
val = rtu_rd(RX_CTR);
TRACE(TRACE_INFO,
"RTU eXtension: read hp priorities (for which priorities traffic is "
"considered HP), mask[rd]=0x%x", RTU_RX_CTR_PRIO_MASK_R(val));
return (uint8_t) RTU_RX_CTR_PRIO_MASK_R(val);
}
/**
* \brief Set the mask which which priorities are considered High Priority (this only
* concerns the traffic which is fast-forwarded)
......@@ -211,35 +215,43 @@ uint8_t rtux_get_hp_prio_mask()
*/
void rtux_set_hp_prio_mask(uint8_t hp_prio_mask)
{
uint32_t mask, val=0;
mask = rtu_rd(RX_CTR);
mask = RTU_RX_CTR_PRIO_MASK_W(hp_prio_mask) | (mask & ~RTU_RX_CTR_PRIO_MASK_MASK);
rtu_wr(RX_CTR,mask);
val = rtu_rd(RX_CTR);
TRACE(TRACE_INFO,"RTU eXtension: set hp priorities (for which priorities traffic is "
"considered HP), mask[wr]=0x%x => mask[rd]=0x%x",mask, RTU_RX_CTR_PRIO_MASK_R(val));
uint32_t mask, val = 0;
mask = rtu_rd(RX_CTR);
mask =
RTU_RX_CTR_PRIO_MASK_W(hp_prio_mask) | (mask &
~RTU_RX_CTR_PRIO_MASK_MASK);
rtu_wr(RX_CTR, mask);
val = rtu_rd(RX_CTR);
TRACE(TRACE_INFO,
"RTU eXtension: set hp priorities (for which priorities traffic is "
"considered HP), mask[wr]=0x%x => mask[rd]=0x%x", mask,
RTU_RX_CTR_PRIO_MASK_R(val));
}
/**
* \brief Read number of virtual port on which CPU is connected to SWcore
* @return port number
*/
int rtux_get_cpu_port()
{
uint32_t mask;
int i =0;
mask = rtu_rd(CPU_PORT);
TRACE(TRACE_INFO,"RTU eXtension: reading mask indicating which (virtual) port is connected"
"to CPU mask=0x%x", RTU_CPU_PORT_MASK_R(mask));
for(i=0;i<= MAX_PORT+1;i++)
{
if(mask & 0x1) return i;
else mask = mask >> 1;
}
return -1;
uint32_t mask;
int i = 0;
mask = rtu_rd(CPU_PORT);
TRACE(TRACE_INFO,
"RTU eXtension: reading mask indicating which (virtual) port is connected"
"to CPU mask=0x%x", RTU_CPU_PORT_MASK_R(mask));
for (i = 0; i <= MAX_PORT + 1; i++) {
if (mask & 0x1)
return i;
else
mask = mask >> 1;
}
return -1;
}
/**
* \brief Setting (enabling/disabling) fast forwarding (few cycles, using special
* fast-match engine) and features
......@@ -251,24 +263,32 @@ int rtux_get_cpu_port()
* @param mac_br enable fast forwarding of range Broadcast traffic
* @param at_fm configure behavior of when the full match is to slow (0=drop, 1=broadcast within VLAN)
*/
void rtux_set_feature_ctrl(int mr, int mac_ptp, int mac_ll, int mac_single, int mac_range,
int mac_br, int at_fm)
void rtux_set_feature_ctrl(int mr, int mac_ptp, int mac_ll, int mac_single,
int mac_range, int mac_br, int at_fm)
{
uint32_t mask;
mask = rtu_rd(RX_CTR);
mask = 0xFFFFFF80 & mask;
if(mr) mask = RTU_RX_CTR_MR_ENA | mask;
if(mac_ptp) mask = RTU_RX_CTR_FF_MAC_PTP | mask;
if(mac_ll) mask = RTU_RX_CTR_FF_MAC_LL | mask;
if(mac_single) mask = RTU_RX_CTR_FF_MAC_SINGLE | mask;
if(mac_range) mask = RTU_RX_CTR_FF_MAC_RANGE | mask;
if(mac_br) mask = RTU_RX_CTR_FF_MAC_BR | mask;
if(at_fm) mask = RTU_RX_CTR_AT_FMATCH_TOO_SLOW | mask;
rtu_wr(RX_CTR, mask);
rtux_disp_ctrl();
uint32_t mask;
mask = rtu_rd(RX_CTR);
mask = 0xFFFFFF80 & mask;
if (mr)
mask = RTU_RX_CTR_MR_ENA | mask;
if (mac_ptp)
mask = RTU_RX_CTR_FF_MAC_PTP | mask;
if (mac_ll)
mask = RTU_RX_CTR_FF_MAC_LL | mask;
if (mac_single)
mask = RTU_RX_CTR_FF_MAC_SINGLE | mask;
if (mac_range)
mask = RTU_RX_CTR_FF_MAC_RANGE | mask;
if (mac_br)
mask = RTU_RX_CTR_FF_MAC_BR | mask;
if (at_fm)
mask = RTU_RX_CTR_AT_FMATCH_TOO_SLOW | mask;
rtu_wr(RX_CTR, mask);
rtux_disp_ctrl();
}
/**
* \brief Sets forwarding of High Priority and/or unrecognized traffic to CPU (by default
* such traffic is not forwarded)
......@@ -277,55 +297,84 @@ void rtux_set_feature_ctrl(int mr, int mac_ptp, int mac_ll, int mac_single, int
*/
void rtux_set_fw_to_CPU(int hp, int unrec)
{
uint32_t mask;
mask = rtu_rd(RX_CTR);
mask = 0xFFF0FFFF & mask;
if(hp) mask = RTU_RX_CTR_HP_FW_CPU_ENA | mask;
if(unrec) mask = RTU_RX_CTR_UREC_FW_CPU_ENA | mask;
rtu_wr(RX_CTR, mask);
uint32_t mask;
mask = rtu_rd(RX_CTR);
mask = 0xFFF0FFFF & mask;
if (hp)
mask = RTU_RX_CTR_HP_FW_CPU_ENA | mask;
if (unrec)
mask = RTU_RX_CTR_UREC_FW_CPU_ENA | mask;
rtu_wr(RX_CTR, mask);
}
void rtux_disp_ctrl(void)
{
uint32_t mask;
mask = rtu_rd(RX_CTR);
TRACE(TRACE_INFO,"RTU eXtension features (read):");
if(RTU_RX_CTR_MR_ENA & mask)
{TRACE(TRACE_INFO,"\t (1 ) Port Mirroring - enabled"); }
else
{TRACE(TRACE_INFO,"\t (1 ) Port Mirroring - disabled");}
if(RTU_RX_CTR_FF_MAC_PTP & mask)
{TRACE(TRACE_INFO,"\t (2 ) PTP fast forward - enabled"); }
else
{TRACE(TRACE_INFO,"\t (2 ) PTP fast forward - disabled");}
if(RTU_RX_CTR_FF_MAC_LL & mask)
{TRACE(TRACE_INFO,"\t (4 ) Link-limited traffic (BPDU) fast forward - enabled"); }
else
{TRACE(TRACE_INFO,"\t (4 ) Link-limited traffic (BPDU) fast forward - disabled");}
if(RTU_RX_CTR_FF_MAC_SINGLE & mask)
{TRACE(TRACE_INFO,"\t (8 ) Single configured MACs fast forward - enabled"); }
else
{TRACE(TRACE_INFO,"\t (8 ) Single configured MACs fast forward - disabled");}
if(RTU_RX_CTR_FF_MAC_RANGE & mask)
{TRACE(TRACE_INFO,"\t (16) Range of configured MACs fast forward - enabled"); }
else
{TRACE(TRACE_INFO,"\t (16) Range of configured MACs fast forward - disabled");}
if(RTU_RX_CTR_FF_MAC_BR & mask)
{TRACE(TRACE_INFO,"\t (32) Broadcast fast forward - enabled"); }
else
{TRACE(TRACE_INFO,"\t (32) Broadcast fast forward - disabled");}
if(RTU_RX_CTR_AT_FMATCH_TOO_SLOW & mask)
{TRACE(TRACE_INFO,"\t (64) When fast match engine too slow - braodcast processed frame");}
else
{TRACE(TRACE_INFO,"\t (64) When fast match engine too slow - drop processed frame");}
if(RTU_RX_CTR_FORCE_FAST_MATCH_ENA & mask)
{TRACE(TRACE_INFO,"\t DBG Force Fast Mach Mechanism - enabled");}
else
{TRACE(TRACE_INFO,"\t DBG Force Fast Mach Mechanism - disabled");}
if(RTU_RX_CTR_FORCE_FULL_MATCH_ENA & mask)
{TRACE(TRACE_INFO,"\t DBG Force Full Mach Mechanism - enabled");}
else
{TRACE(TRACE_INFO,"\t DBG Force Full Mach Mechanism - disabled");}
uint32_t mask;
mask = rtu_rd(RX_CTR);
TRACE(TRACE_INFO, "RTU eXtension features (read):");
if (RTU_RX_CTR_MR_ENA & mask) {
TRACE(TRACE_INFO,
"\t (1 ) Port Mirroring - enabled");
} else {
TRACE(TRACE_INFO,
"\t (1 ) Port Mirroring - disabled");
}
if (RTU_RX_CTR_FF_MAC_PTP & mask) {
TRACE(TRACE_INFO,
"\t (2 ) PTP fast forward - enabled");
} else {
TRACE(TRACE_INFO,
"\t (2 ) PTP fast forward - disabled");
}
if (RTU_RX_CTR_FF_MAC_LL & mask) {
TRACE(TRACE_INFO,
"\t (4 ) Link-limited traffic (BPDU) fast forward - enabled");
} else {
TRACE(TRACE_INFO,
"\t (4 ) Link-limited traffic (BPDU) fast forward - disabled");
}
if (RTU_RX_CTR_FF_MAC_SINGLE & mask) {
TRACE(TRACE_INFO,
"\t (8 ) Single configured MACs fast forward - enabled");
} else {
TRACE(TRACE_INFO,
"\t (8 ) Single configured MACs fast forward - disabled");
}
if (RTU_RX_CTR_FF_MAC_RANGE & mask) {
TRACE(TRACE_INFO,
"\t (16) Range of configured MACs fast forward - enabled");
} else {
TRACE(TRACE_INFO,
"\t (16) Range of configured MACs fast forward - disabled");
}
if (RTU_RX_CTR_FF_MAC_BR & mask) {
TRACE(TRACE_INFO,
"\t (32) Broadcast fast forward - enabled");
} else {
TRACE(TRACE_INFO,
"\t (32) Broadcast fast forward - disabled");
}
if (RTU_RX_CTR_AT_FMATCH_TOO_SLOW & mask) {
TRACE(TRACE_INFO,
"\t (64) When fast match engine too slow - braodcast processed frame");
} else {
TRACE(TRACE_INFO,
"\t (64) When fast match engine too slow - drop processed frame");
}
if (RTU_RX_CTR_FORCE_FAST_MATCH_ENA & mask) {
TRACE(TRACE_INFO,
"\t DBG Force Fast Mach Mechanism - enabled");
} else {
TRACE(TRACE_INFO,
"\t DBG Force Fast Mach Mechanism - disabled");
}
if (RTU_RX_CTR_FORCE_FULL_MATCH_ENA & mask) {
TRACE(TRACE_INFO,
"\t DBG Force Full Mach Mechanism - enabled");
} else {
TRACE(TRACE_INFO,
"\t DBG Force Full Mach Mechanism - disabled");
}
}
......@@ -25,7 +25,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WHITERABBIT_RTU_EXT_DRV_H
#define __WHITERABBIT_RTU_EXT_DRV_H
......@@ -34,14 +33,15 @@
int rtux_init(void);
void rtux_add_ff_mac_single(int mac_id, int valid, uint8_t mac[ETH_ALEN]);
void rtux_add_ff_mac_range(int mac_id, int valid, uint8_t mac_lower[ETH_ALEN],
uint8_t mac_upper[ETH_ALEN]);
void rtux_set_port_mirror(uint32_t mirror_src_mask, uint32_t mirror_dst_mask, int rx, int tx);
uint8_t mac_upper[ETH_ALEN]);
void rtux_set_port_mirror(uint32_t mirror_src_mask, uint32_t mirror_dst_mask,
int rx, int tx);
void rtux_set_hp_prio_mask(uint8_t hp_prio_mask);
uint8_t rtux_get_hp_prio_mask();
int rtux_get_cpu_port();
void rtux_set_feature_ctrl(int mr, int mac_ptp, int mac_ll, int mac_single, int mac_range,
int mac_br, int at_fm);
void rtux_set_feature_ctrl(int mr, int mac_ptp, int mac_ll, int mac_single,
int mac_range, int mac_br, int at_fm);
void rtux_set_fw_to_CPU(int hp, int unrec);
void rtux_disp_ctrl(void);
......
......@@ -31,7 +31,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
......@@ -45,27 +44,25 @@
#include "rtu_drv.h"
#include "rtu_hash.h"
// Used to declare HW request types.
#define HW_WRITE_REQ 0
#define HW_REMOVE_REQ 1
/**
* \brief Filtering Database entry handle.
*/
struct fd_handle {
struct rtu_addr addr;
struct filtering_entry *entry_ptr; // pointer to entry at mirror fd
struct rtu_addr addr;
struct filtering_entry *entry_ptr; // pointer to entry at mirror fd
};
/**
* \brief HW (HTAB or HCAM) write request.
*/
struct hw_req {
int type; // WRITE or CLEAN
struct fd_handle handle; // filtering database entry handle
struct hw_req *next; // linked list
int type; // WRITE or CLEAN
struct fd_handle handle; // filtering database entry handle
struct hw_req *next; // linked list
};
/**
......@@ -99,7 +96,8 @@ static pthread_mutex_t fd_mutex;
static struct hw_req *tail(struct hw_req *head);
static void clean_list(struct hw_req *head);
static int hw_request(int type, struct rtu_addr addr, struct filtering_entry *ent);
static int hw_request(int type, struct rtu_addr addr,
struct filtering_entry *ent);
static void clean_fd(void);
static void clean_vd(void);
......@@ -110,7 +108,6 @@ static void rtu_fd_commit(void);
static void rtu_fd_age_out(void);
static void rtu_fd_age_update(void);
/**
* \brief Initializes the RTU filtering database.
* @param poly hash polinomial.
......@@ -118,45 +115,41 @@ static void rtu_fd_age_update(void);
*/
int rtu_fd_init(uint16_t poly, unsigned long aging)
{
uint32_t bitmap[RTU_ENTRIES / 32];
int err;
TRACE(TRACE_INFO, "clean filtering database.");
clean_fd(); // clean filtering database
TRACE(TRACE_INFO, "clean vlan database.");
clean_vd(); // clean VLAN database
TRACE(TRACE_INFO, "clean aging map.");
rtu_read_aging_bitmap(bitmap); // clean aging registers
TRACE(TRACE_INFO, "set aging time [%d].", aging);
aging_time = aging;
err = pthread_mutex_init(&fd_mutex, NULL);
if (err)
return err;
TRACE(TRACE_INFO, "set hash poly.");
rtu_fd_set_hash_poly(poly);
return 0;
uint32_t bitmap[RTU_ENTRIES / 32];
int err;
TRACE(TRACE_INFO, "clean filtering database.");
clean_fd(); // clean filtering database
TRACE(TRACE_INFO, "clean vlan database.");
clean_vd(); // clean VLAN database
TRACE(TRACE_INFO, "clean aging map.");
rtu_read_aging_bitmap(bitmap); // clean aging registers
TRACE(TRACE_INFO, "set aging time [%d].", aging);
aging_time = aging;
err = pthread_mutex_init(&fd_mutex, NULL);
if (err)
return err;
TRACE(TRACE_INFO, "set hash poly.");
rtu_fd_set_hash_poly(poly);
return 0;
}
static int htab_search (
uint8_t mac[ETH_ALEN],
uint8_t fid,
struct filtering_entry **ent)
static int htab_search(uint8_t mac[ETH_ALEN],
uint8_t fid, struct filtering_entry **ent)
{
int i, j;
for(i=0; i<HTAB_ENTRIES; i++)
for(j=0; j<RTU_BUCKETS; j++)
{
for (i = 0; i < HTAB_ENTRIES; i++)
for (j = 0; j < RTU_BUCKETS; j++) {
struct filtering_entry *tmp = &rtu_htab[i][j];
if(!tmp->valid)
if (!tmp->valid)
continue;
if(mac_equal(tmp->mac, mac) && tmp->fid == fid)
{
if (mac_equal(tmp->mac, mac) && tmp->fid == fid) {
*ent = tmp;
return 1;
}
......@@ -169,14 +162,13 @@ static int htab_count_buckets(struct rtu_addr addr)
{
int n = 0, i;
for(i=0; i<RTU_BUCKETS; i++)
if(rtu_htab[addr.hash][i].valid)
for (i = 0; i < RTU_BUCKETS; i++)
if (rtu_htab[addr.hash][i].valid)
n++;
return n;
}
/**
* \brief Creates or updates a filtering entry in the filtering database.
* @param mac MAC address specification
......@@ -186,75 +178,77 @@ static int htab_count_buckets(struct rtu_addr addr)
* @param dynamic it indicates whether it's a dynamic entry
* @return 0 if entry was created or updated. -ENOMEM if no space is available.
*/
int rtu_fd_create_entry(uint8_t mac[ETH_ALEN], uint16_t vid, uint32_t port_mask, int dynamic, int at_existing_entry)
int rtu_fd_create_entry(uint8_t mac[ETH_ALEN], uint16_t vid, uint32_t port_mask,
int dynamic, int at_existing_entry)
{
struct filtering_entry *ent; // pointer to scan hashtable
uint8_t fid; // Filtering database identifier
int ret = 0; // return value
uint32_t mask_src, mask_dst; // used to check port masks update
struct rtu_addr eaddr;
pthread_mutex_lock(&fd_mutex);
// if VLAN is registered (otherwise just ignore request)
if (! vlan_tab[vid].drop) {
// Obtain FID from VLAN database
fid = vlan_tab[vid].fid;
/* Case 1: entry already present in the hashtable */
if(htab_search(mac, fid, &ent))
{
TRACE_DBG(TRACE_INFO, "Entry for mac %s already found.", mac_to_string(mac));
if(at_existing_entry == ADD_TO_EXISTING) // enable multipath for redundancy
mask_dst = port_mask | ent->port_mask_dst ;
else
mask_dst = port_mask; //ML: aging bugfix-> if we receive ureq for an existing entry,
//it means that the port moved, so we override the existing mask...
mask_src = 0xFFFFFFFF;//ML: filtering on ingress is optional according to 802.1Q-2012
//by default it should not happen. TODO: add optional config
if ((ent->port_mask_dst != mask_dst) ||
(ent->port_mask_src != mask_src)) { // something new
ent->port_mask_dst = mask_dst;
ent->port_mask_src = mask_src;
ent->last_access_t = now(); //ML: update time always when updating the entry
hw_request(HW_WRITE_REQ, ent->addr, ent);
}
/* Case 2: MAC not found */
} else {
int n_buckets;
eaddr.hash = rtu_hash(mac, fid);
n_buckets = htab_count_buckets(eaddr);
if(n_buckets == RTU_BUCKETS)
{
TRACE(TRACE_ERROR, "Hash %03x has no buckets left.", eaddr.hash);
return -ENOMEM;
}
eaddr.bucket = n_buckets;
ent = &rtu_htab[eaddr.hash][eaddr.bucket];
ent->addr = eaddr;
TRACE(TRACE_INFO, "Created new entry for MAC %s : hash %03x:%d.", mac_to_string(mac), eaddr.hash, eaddr.bucket);
ent->valid = 1;
ent->fid = fid;
ent->port_mask_dst = port_mask;
ent->port_mask_src = 0xFFFFFFFF;//ML: filtering on ingress is optional according to 802.1Q-2012
//by default it should not happen. TODO: add optional config
ent->dynamic = dynamic;
ent->last_access_t = now();
mac_copy(ent->mac, mac);
hw_request(HW_WRITE_REQ, eaddr, ent);
}
struct filtering_entry *ent; // pointer to scan hashtable
uint8_t fid; // Filtering database identifier
int ret = 0; // return value
uint32_t mask_src, mask_dst; // used to check port masks update
struct rtu_addr eaddr;
pthread_mutex_lock(&fd_mutex);
// if VLAN is registered (otherwise just ignore request)
if (!vlan_tab[vid].drop) {
// Obtain FID from VLAN database
fid = vlan_tab[vid].fid;
/* Case 1: entry already present in the hashtable */
if (htab_search(mac, fid, &ent)) {
TRACE_DBG(TRACE_INFO, "Entry for mac %s already found.",
mac_to_string(mac));
if (at_existing_entry == ADD_TO_EXISTING) // enable multipath for redundancy
mask_dst = port_mask | ent->port_mask_dst;
else
mask_dst = port_mask; //ML: aging bugfix-> if we receive ureq for an existing entry,
//it means that the port moved, so we override the existing mask...
mask_src = 0xFFFFFFFF; //ML: filtering on ingress is optional according to 802.1Q-2012
//by default it should not happen. TODO: add optional config
if ((ent->port_mask_dst != mask_dst) || (ent->port_mask_src != mask_src)) { // something new
ent->port_mask_dst = mask_dst;
ent->port_mask_src = mask_src;
ent->last_access_t = now(); //ML: update time always when updating the entry
hw_request(HW_WRITE_REQ, ent->addr, ent);
}
/* Case 2: MAC not found */
} else {
int n_buckets;
eaddr.hash = rtu_hash(mac, fid);
n_buckets = htab_count_buckets(eaddr);
if (n_buckets == RTU_BUCKETS) {
TRACE(TRACE_ERROR,
"Hash %03x has no buckets left.",
eaddr.hash);
return -ENOMEM;
}
}
rtu_fd_commit();
pthread_mutex_unlock(&fd_mutex);
return ret;
eaddr.bucket = n_buckets;
ent = &rtu_htab[eaddr.hash][eaddr.bucket];
ent->addr = eaddr;
TRACE(TRACE_INFO,
"Created new entry for MAC %s : hash %03x:%d.",
mac_to_string(mac), eaddr.hash, eaddr.bucket);
ent->valid = 1;
ent->fid = fid;
ent->port_mask_dst = port_mask;
ent->port_mask_src = 0xFFFFFFFF; //ML: filtering on ingress is optional according to 802.1Q-2012
//by default it should not happen. TODO: add optional config
ent->dynamic = dynamic;
ent->last_access_t = now();
mac_copy(ent->mac, mac);
hw_request(HW_WRITE_REQ, eaddr, ent);
}
}
rtu_fd_commit();
pthread_mutex_unlock(&fd_mutex);
return ret;
}
/**
......@@ -271,10 +265,10 @@ int rtu_fd_create_entry(uint8_t mac[ETH_ALEN], uint16_t vid, uint32_t port_mask,
*/
void rtu_fd_set_hash_poly(uint16_t poly)
{
pthread_mutex_lock(&fd_mutex);
rtu_write_hash_poly(poly);
rtu_hash_set_poly(poly);
pthread_mutex_unlock(&fd_mutex);
pthread_mutex_lock(&fd_mutex);
rtu_write_hash_poly(poly);
rtu_hash_set_poly(poly);
pthread_mutex_unlock(&fd_mutex);
}
/**
......@@ -284,41 +278,39 @@ void rtu_fd_set_hash_poly(uint16_t poly)
*/
int rtu_fd_set_aging_time(unsigned long t)
{
if ((t < 10) || (t > 1000000))
return -EINVAL;
aging_time = t;
return 0;
if ((t < 10) || (t > 1000000))
return -EINVAL;
aging_time = t;
return 0;
}
/**
* \brief Deletes old filtering entries from filtering database to support
* changes in active topology.
*/
void rtu_fd_flush(void)
{
rtu_fd_age_update(); // Update filtering entries age
rtu_fd_age_update(); // Update filtering entries age
pthread_mutex_lock(&fd_mutex);
rtu_fd_age_out(); // Remove old entries
pthread_mutex_unlock(&fd_mutex);
pthread_mutex_lock(&fd_mutex);
rtu_fd_age_out(); // Remove old entries
pthread_mutex_unlock(&fd_mutex);
}
struct filtering_entry *rtu_fd_lookup_htab_entry(int index)
{
int i, j, n = 0;
for(i=0;i<RTU_ENTRIES/RTU_BUCKETS;i++) {
for(j=0;j<RTU_BUCKETS;j++)
{
if(rtu_htab[i][j].valid)
{
if(n == index) return &rtu_htab[i][j];
for (i = 0; i < RTU_ENTRIES / RTU_BUCKETS; i++) {
for (j = 0; j < RTU_BUCKETS; j++) {
if (rtu_htab[i][j].valid) {
if (n == index)
return &rtu_htab[i][j];
n++;
}
}
}
return NULL;
}
return NULL;
}
//---------------------------------------------
......@@ -328,55 +320,55 @@ struct filtering_entry *rtu_fd_lookup_htab_entry(int index)
/**
* Returns pointer to last element in hw_req_list.
*/
static struct hw_req *tail(struct hw_req *head){
struct hw_req *ptr;
static struct hw_req *tail(struct hw_req *head)
{
struct hw_req *ptr;
for(ptr = head; ptr->next; ptr = ptr->next);
return ptr;
for (ptr = head; ptr->next; ptr = ptr->next) ;
return ptr;
}
/**
* Removes all elements from the hw_req_list
*/
static void clean_list(struct hw_req *head){
struct hw_req *ptr;
while(head) {
ptr = head;
head = head->next;
free(ptr);
}
}
static void clean_list(struct hw_req *head)
{
struct hw_req *ptr;
while (head) {
ptr = head;
head = head->next;
free(ptr);
}
}
static int hw_request(int type, struct rtu_addr addr, struct filtering_entry *ent)
static int hw_request(int type, struct rtu_addr addr,
struct filtering_entry *ent)
{
struct hw_req *req;
req = (struct hw_req*) malloc(sizeof(struct hw_req));
if(!req)
return -ENOMEM;
struct hw_req *req;
req->type = type;
req->handle.addr = addr;
req->handle.entry_ptr = ent;
req->next = NULL;
req = (struct hw_req *)malloc(sizeof(struct hw_req));
if (!req)
return -ENOMEM;
if(!hw_req_list)
hw_req_list = req;
else
tail(hw_req_list)->next = req;
req->type = type;
req->handle.addr = addr;
req->handle.entry_ptr = ent;
req->next = NULL;
if (!hw_req_list)
hw_req_list = req;
else
tail(hw_req_list)->next = req;
return 0;
return 0;
}
static inline int to_mem_addr(struct rtu_addr addr)
{
return (( 0x07FF & addr.hash ) << 5 ) | ((0x0003 & addr.bucket) << 3);
return ((0x07FF & addr.hash) << 5) | ((0x0003 & addr.bucket) << 3);
}
/**
* \brief Checks whether a given pair (mac,fid) is at HTAB
* @param mac mac address
......@@ -387,7 +379,6 @@ static inline int to_mem_addr(struct rtu_addr addr)
* HTAB was full for the corresponding hash. -EINVAL if bucket >= RTU_BUCKETS
*/
/**
* Filtering database initialisation.
*/
......@@ -395,7 +386,7 @@ static void clean_fd(void)
{
memset(&rtu_htab, 0, sizeof(rtu_htab));
rtu_clean_htab();
rtu_clean_htab();
}
/**
......@@ -403,23 +394,23 @@ static void clean_fd(void)
*/
static void clean_vd(void)
{
int i;
rtu_clean_vlan();
for(i = 1; i < NUM_VLANS; i++) {
vlan_tab[i].drop = 1;
vlan_tab[i].port_mask = 0x0;
}
// First entry reserved for untagged packets.
vlan_tab[0].port_mask = 0xffffffff;
vlan_tab[0].drop = 0;
vlan_tab[0].fid = 0;
vlan_tab[0].has_prio = 0;
vlan_tab[0].prio_override = 0;
vlan_tab[0].prio = 0;
rtu_write_vlan_entry(0, &vlan_tab[0]);
int i;
rtu_clean_vlan();
for (i = 1; i < NUM_VLANS; i++) {
vlan_tab[i].drop = 1;
vlan_tab[i].port_mask = 0x0;
}
// First entry reserved for untagged packets.
vlan_tab[0].port_mask = 0xffffffff;
vlan_tab[0].drop = 0;
vlan_tab[0].fid = 0;
vlan_tab[0].has_prio = 0;
vlan_tab[0].prio_override = 0;
vlan_tab[0].prio = 0;
rtu_write_vlan_entry(0, &vlan_tab[0]);
}
/**
......@@ -427,70 +418,72 @@ static void clean_vd(void)
*/
static void rtu_fd_age_update(void)
{
int i; // Aging Bitmap word loop index
int j; // Word bits loop index
uint32_t agr_word; // Aux var for manipulating aging RAM
uint16_t hash; // HTAB entry hash (index)
int bucket; // HTAB entry bucket
int bit_cnt; // Absolute bit counter
unsigned long t; // Time since epoch (secs)
uint32_t bitmap[RTU_ENTRIES / 32];
rtu_read_aging_bitmap(bitmap);
// Update 'last access time' for accessed entries
t = now();
// HTAB
for(i = 0; i < RTU_ENTRIES / 32; i++)
for(j = 0; j < 32; j++) {
agr_word = bitmap[i];
if(agr_word & (1 << j)) {
bit_cnt = (i << 5) | j;
hash = bit_cnt >> 2; // 4 buckets per hash
bucket = bit_cnt & 0x03; // last 2 bits
if(!rtu_htab[hash][bucket].dynamic)
continue;
if (0)
TRACE(
TRACE_INFO,
"Updated htab entry age: mac = %s, hash = %03x:%d, delta_t = %d",
mac_to_string(rtu_htab[hash][bucket].mac),
hash,
bucket,
t - rtu_htab[hash][bucket].last_access_t
);
rtu_htab[hash][bucket].age = t - rtu_htab[hash][bucket].last_access_t;
rtu_htab[hash][bucket].last_access_t = t;
}
}
int i; // Aging Bitmap word loop index
int j; // Word bits loop index
uint32_t agr_word; // Aux var for manipulating aging RAM
uint16_t hash; // HTAB entry hash (index)
int bucket; // HTAB entry bucket
int bit_cnt; // Absolute bit counter
unsigned long t; // Time since epoch (secs)
uint32_t bitmap[RTU_ENTRIES / 32];
rtu_read_aging_bitmap(bitmap);
// Update 'last access time' for accessed entries
t = now();
// HTAB
for (i = 0; i < RTU_ENTRIES / 32; i++)
for (j = 0; j < 32; j++) {
agr_word = bitmap[i];
if (agr_word & (1 << j)) {
bit_cnt = (i << 5) | j;
hash = bit_cnt >> 2; // 4 buckets per hash
bucket = bit_cnt & 0x03; // last 2 bits
if (!rtu_htab[hash][bucket].dynamic)
continue;
if (0)
TRACE(TRACE_INFO,
"Updated htab entry age: mac = %s, hash = %03x:%d, delta_t = %d",
mac_to_string(rtu_htab[hash]
[bucket].mac), hash,
bucket,
t -
rtu_htab[hash][bucket].
last_access_t);
rtu_htab[hash][bucket].age =
t - rtu_htab[hash][bucket].last_access_t;
rtu_htab[hash][bucket].last_access_t = t;
}
}
}
void rtu_fd_clear_entries_for_port(int dest_port)
{
int i; // loop index
int j; // bucket loop index
struct filtering_entry *ent; // pointer to scan tables
for (i = HTAB_ENTRIES; i-- > 0;) {
for (j = RTU_BUCKETS; j-- > 0;) {
ent = &rtu_htab[i][j];
if(ent->valid && ent->dynamic) {
if(ent->port_mask_dst == (1<<dest_port))
hw_request(HW_REMOVE_REQ, ent->addr, ent);
else {
TRACE(TRACE_ERROR, "cleaning multicast entries not supported yet...\n");
}
}
}
}
// commit changes
rtu_fd_commit();
int i; // loop index
int j; // bucket loop index
struct filtering_entry *ent; // pointer to scan tables
for (i = HTAB_ENTRIES; i-- > 0;) {
for (j = RTU_BUCKETS; j-- > 0;) {
ent = &rtu_htab[i][j];
if (ent->valid && ent->dynamic) {
if (ent->port_mask_dst == (1 << dest_port))
hw_request(HW_REMOVE_REQ, ent->addr,
ent);
else {
TRACE(TRACE_ERROR,
"cleaning multicast entries not supported yet...\n");
}
}
}
}
// commit changes
rtu_fd_commit();
}
/**
......@@ -499,31 +492,29 @@ void rtu_fd_clear_entries_for_port(int dest_port)
*/
static void rtu_fd_age_out(void)
{
int i; // loop index
int j; // bucket loop index
struct filtering_entry *ent; // pointer to scan tables
unsigned long t; // (secs)
t = now() - aging_time;
// HTAB
for (i = HTAB_ENTRIES; i-- > 0;) {
for (j = RTU_BUCKETS; j-- > 0;) {
ent = &rtu_htab[i][j];
if(ent->valid && ent->dynamic && (time_after(t, ent->last_access_t) || ent->force_remove)){
TRACE(
TRACE_INFO,
"Deleting htab entry: mac = %s, hash = 0x%x, bucket = %d, forced=%d\n",
mac_to_string(ent->mac),
i,
j,
ent->force_remove
);
hw_request(HW_REMOVE_REQ, ent->addr, ent);
}
}
}
// commit changes
rtu_fd_commit();
int i; // loop index
int j; // bucket loop index
struct filtering_entry *ent; // pointer to scan tables
unsigned long t; // (secs)
t = now() - aging_time;
// HTAB
for (i = HTAB_ENTRIES; i-- > 0;) {
for (j = RTU_BUCKETS; j-- > 0;) {
ent = &rtu_htab[i][j];
if (ent->valid && ent->dynamic
&& (time_after(t, ent->last_access_t)
|| ent->force_remove)) {
TRACE(TRACE_INFO,
"Deleting htab entry: mac = %s, hash = 0x%x, bucket = %d, forced=%d\n",
mac_to_string(ent->mac), i, j,
ent->force_remove);
hw_request(HW_REMOVE_REQ, ent->addr, ent);
}
}
}
// commit changes
rtu_fd_commit();
}
/**
......@@ -534,41 +525,46 @@ static void delete_htab_entry(struct rtu_addr addr)
{
int i, n_buckets = htab_count_buckets(addr);
TRACE(TRACE_INFO, "Deleted entry for MAC %s : hash %03x:%d.", mac_to_string(rtu_htab[addr.hash][addr.bucket].mac), addr.hash, addr.bucket);
TRACE(TRACE_INFO, "Deleted entry for MAC %s : hash %03x:%d.",
mac_to_string(rtu_htab[addr.hash][addr.bucket].mac), addr.hash,
addr.bucket);
memset(&rtu_htab[addr.hash][addr.bucket], 0, sizeof(struct filtering_entry));
memset(&rtu_htab[addr.hash][addr.bucket], 0,
sizeof(struct filtering_entry));
if(addr.bucket < n_buckets-1)
if (addr.bucket < n_buckets - 1)
memmove(&rtu_htab[addr.hash][addr.bucket],
&rtu_htab[addr.hash][addr.bucket+1],
(n_buckets-addr.bucket-1) * sizeof(struct filtering_entry));
&rtu_htab[addr.hash][addr.bucket + 1],
(n_buckets - addr.bucket -
1) * sizeof(struct filtering_entry));
for(i=0; i<n_buckets; i++)
{
for (i = 0; i < n_buckets; i++) {
struct rtu_addr a;
a.hash = addr.hash;
a.bucket = i;
rtu_write_htab_entry(to_mem_addr(a), &rtu_htab[a.hash][a.bucket], (i == n_buckets-1) ? 1 : 0);
rtu_write_htab_entry(to_mem_addr(a),
&rtu_htab[a.hash][a.bucket],
(i == n_buckets - 1) ? 1 : 0);
}
}
static void rtu_hw_commit(void)
{
struct hw_req *req; // used to scan hw_req_list
struct hw_req *req; // used to scan hw_req_list
for(req = hw_req_list; req; req = req->next){
switch(req->type){
case HW_WRITE_REQ:
rtu_write_htab_entry(to_mem_addr(req->handle.addr), req->handle.entry_ptr, 1);
break;
for (req = hw_req_list; req; req = req->next) {
switch (req->type) {
case HW_WRITE_REQ:
rtu_write_htab_entry(to_mem_addr(req->handle.addr),
req->handle.entry_ptr, 1);
break;
case HW_REMOVE_REQ:
delete_htab_entry(req->handle.addr);
break;
case HW_REMOVE_REQ:
delete_htab_entry(req->handle.addr);
break;
}
}
}
}
}
/**
......@@ -576,14 +572,14 @@ static void rtu_hw_commit(void)
*/
static void rtu_fd_commit(void)
{
if(!hw_req_list)
return;
if (!hw_req_list)
return;
rtu_hw_commit();
rtu_hw_commit();
// this list no longer needed
clean_list(hw_req_list);
hw_req_list = NULL;
// this list no longer needed
clean_list(hw_req_list);
hw_req_list = NULL;
}
/**
......@@ -597,8 +593,9 @@ static void rtu_fd_commit(void)
* @param drop Drop frames with this VID
*/
//--------------------------------------------------------------------------------------------
void rtu_fd_create_vlan_entry(int vid, uint32_t port_mask, uint8_t fid, uint8_t prio,
int has_prio,int prio_override, int drop)
void rtu_fd_create_vlan_entry(int vid, uint32_t port_mask, uint8_t fid,
uint8_t prio, int has_prio, int prio_override,
int drop)
{
/*****************************************************************************************
* this is obviously wrong - the number of ports needs to be passed here in some beautiful
......@@ -608,22 +605,22 @@ void rtu_fd_create_vlan_entry(int vid, uint32_t port_mask, uint8_t fid, uint8_t
* principle we might not need it in the end, but it would be good if it was possible to
* say whether we want or not
*/
#include <stddef.h>
#define rtu_rd(reg) \
#include <stddef.h>
#define rtu_rd(reg) \
_fpga_readl(FPGA_BASE_RTU + offsetof(struct RTU_WB, reg))
int port_num= RTU_PSR_N_PORTS_R(rtu_rd(PSR));
int port_num = RTU_PSR_N_PORTS_R(rtu_rd(PSR));
/****************************************************************************************/
if(port_mask == 0x0 && drop == 1)
vlan_tab[vid].port_mask = 0x0;
else
vlan_tab[vid].port_mask = port_mask | (0x1 << port_num);
vlan_tab[vid].drop = drop;
vlan_tab[vid].fid = fid;
vlan_tab[vid].has_prio = has_prio;
vlan_tab[vid].prio_override = prio_override;
vlan_tab[vid].prio = prio;
rtu_write_vlan_entry(vid, &vlan_tab[vid]);
if (port_mask == 0x0 && drop == 1)
vlan_tab[vid].port_mask = 0x0;
else
vlan_tab[vid].port_mask = port_mask | (0x1 << port_num);
vlan_tab[vid].drop = drop;
vlan_tab[vid].fid = fid;
vlan_tab[vid].has_prio = has_prio;
vlan_tab[vid].prio_override = prio_override;
vlan_tab[vid].prio = prio;
rtu_write_vlan_entry(vid, &vlan_tab[vid]);
}
/**
......@@ -633,19 +630,19 @@ void rtu_fd_create_vlan_entry(int vid, uint32_t port_mask, uint8_t fid, uint8_t
*/
struct vlan_table_entry *rtu_vlan_entry_get(int vid)
{
// First entry reserved for untagged packets.
if(vid > NUM_VLANS) return NULL;
if(vlan_tab[vid].drop == 0) vlan_entry_rd(vid);
return &vlan_tab[vid];
// First entry reserved for untagged packets.
if (vid > NUM_VLANS)
return NULL;
if (vlan_tab[vid].drop == 0)
vlan_entry_rd(vid);
return &vlan_tab[vid];
}
void vlan_entry_rd(int vid)
{
// First entry reserved for untagged packets.
TRACE(TRACE_INFO, "vlan_entry_vd: vid %d, drop=%d, fid=%d, port_mask 0x%x",
vid,
vlan_tab[vid].drop,
vlan_tab[vid].fid,
vlan_tab[vid].port_mask
);
// First entry reserved for untagged packets.
TRACE(TRACE_INFO,
"vlan_entry_vd: vid %d, drop=%d, fid=%d, port_mask 0x%x", vid,
vlan_tab[vid].drop, vlan_tab[vid].fid, vlan_tab[vid].port_mask);
}
......@@ -30,7 +30,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WHITERABBIT_RTU_FD_H
#define __WHITERABBIT_RTU_FD_H
......@@ -49,30 +48,29 @@
#define ADD_TO_EXISTING 1
int rtu_fd_init(uint16_t poly, unsigned long aging)
__attribute__((warn_unused_result));
__attribute__ ((warn_unused_result));
int rtu_fd_create_entry(
uint8_t mac[ETH_ALEN],
uint16_t vid,
uint32_t port_map,
int dynamic,
int at_existing_entry
) __attribute__((warn_unused_result));
int rtu_fd_create_entry(uint8_t mac[ETH_ALEN],
uint16_t vid,
uint32_t port_map,
int dynamic,
int at_existing_entry)
__attribute__ ((warn_unused_result));
int rtu_fd_set_aging_time(unsigned long t) __attribute__((warn_unused_result));
int rtu_fd_set_aging_time(unsigned long t) __attribute__ ((warn_unused_result));
void rtu_fd_set_hash_poly(uint16_t poly);
void rtu_fd_flush(void);
void rtu_fd_clear_entries_for_port(int dest_port);
struct filtering_entry * rtu_fd_lookup_htab_entry(int index);
struct filtering_entry *rtu_fd_lookup_htab_entry(int index);
struct filtering_entry *rtu_fd_lookup_htab_entry(int index);
void rtu_fd_create_vlan_entry(int vid, uint32_t port_mask, uint8_t fid, uint8_t prio,
int has_prio,int prio_override, int drop);
void rtu_fd_create_vlan_entry(int vid, uint32_t port_mask, uint8_t fid,
uint8_t prio, int has_prio, int prio_override,
int drop);
void vlan_entry_rd(int vid);
struct vlan_table_entry *rtu_vlan_entry_get(int vid);
#endif /*__WHITERABBIT_RTU_FD_H*/
......@@ -39,19 +39,19 @@ static uint16_t crc16(uint16_t const init_crc, uint16_t const message);
void rtu_hash_set_poly(uint16_t poly)
{
hash_poly = ((0x10000 | poly) << 3 );
hash_poly = ((0x10000 | poly) << 3);
}
uint16_t rtu_hash(uint8_t mac[ETH_ALEN], uint8_t fid)
{
uint16_t hash = 0xFFFF;
uint16_t hash = 0xFFFF;
hash = crc16(hash, (0xFFFF & fid));
hash = crc16(hash, ((uint16_t)mac[0] << 8) | mac[1]);
hash = crc16(hash, ((uint16_t)mac[2] << 8) | mac[3]);
hash = crc16(hash, ((uint16_t)mac[4] << 8) | mac[5]);
hash = crc16(hash, (0xFFFF & fid));
hash = crc16(hash, ((uint16_t) mac[0] << 8) | mac[1]);
hash = crc16(hash, ((uint16_t) mac[2] << 8) | mac[3]);
hash = crc16(hash, ((uint16_t) mac[4] << 8) | mac[5]);
return hash & (HTAB_ENTRIES - 1); /* warning: assumes that HTAB_ENTRIES is a power of 2 */
return hash & (HTAB_ENTRIES - 1); /* warning: assumes that HTAB_ENTRIES is a power of 2 */
}
/*
......@@ -91,24 +91,21 @@ uint16_t rtu_hash(uint8_t mac[ETH_ALEN], uint8_t fid)
*/
static uint16_t crc16(uint16_t const init_crc, uint16_t const message)
{
uint32_t remainder;
int bit;
uint32_t remainder;
int bit;
// Initially, the dividend is the remainder.
remainder = message^init_crc;
// For each bit position in the message....
for (bit = 20; bit > 0; --bit) {
// If the uppermost bit is a 1...
if (remainder & 0x80000) {
// XOR the previous remainder with the divisor.
remainder ^= hash_poly;
}
//Shift the next bit of the message into the remainder.
remainder = (remainder << 1);
}
// Return only the relevant bits of the remainder as CRC.
return (remainder >> 4);
// Initially, the dividend is the remainder.
remainder = message ^ init_crc;
// For each bit position in the message....
for (bit = 20; bit > 0; --bit) {
// If the uppermost bit is a 1...
if (remainder & 0x80000) {
// XOR the previous remainder with the divisor.
remainder ^= hash_poly;
}
//Shift the next bit of the message into the remainder.
remainder = (remainder << 1);
}
// Return only the relevant bits of the remainder as CRC.
return (remainder >> 4);
}
......@@ -49,4 +49,3 @@ void rtu_hash_set_poly(uint16_t poly);
uint16_t rtu_hash(uint8_t mac[ETH_ALEN], uint8_t fid);
#endif /*__WHITERABBIT_RTU_HASH_H*/
......@@ -38,7 +38,6 @@
#include <sys/ioctl.h>
#include <linux/if.h>
#include <trace.h>
#include <switch_hw.h>
#include <hal_client.h>
......@@ -51,7 +50,6 @@
#include "rtu_hash.h"
#include "utils.h"
static pthread_t aging_process;
static pthread_t wripc_process;
......@@ -62,7 +60,6 @@ static struct {
int hw_index;
} port_state[MAX_PORT + 1];
/**
* \brief Creates the static entries in the filtering database
* @return error code
......@@ -70,73 +67,84 @@ static struct {
static int rtu_create_static_entries()
{
uint8_t bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
uint8_t slow_proto_mac[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x01};
uint8_t ptp_mcast_mac[] = {0x01, 0x1b, 0x19, 0x00, 0x00, 0x00};
hexp_port_state_t pstate;
hexp_port_list_t ports;
int i, err;
uint32_t enabled_port_mask = 0;
halexp_query_ports(&ports);
TRACE(TRACE_INFO, "Number of physical ports: %d, active ports: %d\n", ports.num_physical_ports, ports.num_ports);
// VLAN-aware Bridge reserved addresses (802.1Q-2005 Table 8.1)
TRACE(TRACE_INFO,"adding static routes for slow protocols...");
for(i = 0; i < NUM_RESERVED_ADDR; i++) {
slow_proto_mac[5] = i;
err = rtu_fd_create_entry(slow_proto_mac, 0, (1 << ports.num_physical_ports), STATIC, OVERRIDE_EXISTING);
if(err)
return err;
}
memset(port_state, 0, sizeof(port_state));
for(i = 0; i < ports.num_ports; i++) {
halexp_get_port_state(&pstate, ports.port_names[i]);
enabled_port_mask |= (1 << pstate.hw_index);
strncpy(port_state[i].if_name, ports.port_names[i], 16);
port_state[i].is_up = 0;
port_state[i].hw_index = pstate.hw_index;
port_state[i].in_use = 1;
TRACE(
TRACE_INFO,
"adding static route for port %s index %d [mac %s]",
ports.port_names[i],
pstate.hw_index,
mac_to_string(pstate.hw_addr)
);
err = rtu_fd_create_entry(pstate.hw_addr, 0, (1 << ports.num_physical_ports), STATIC, OVERRIDE_EXISTING);
if(err)
return err;
}
// Broadcast MAC
TRACE(TRACE_INFO,"adding static route for broadcast MAC...");
err = rtu_fd_create_entry(bcast_mac, 0, enabled_port_mask | (1 << ports.num_physical_ports), STATIC, OVERRIDE_EXISTING);
err = rtu_fd_create_entry(ptp_mcast_mac, 0, (1 << ports.num_physical_ports), STATIC, OVERRIDE_EXISTING);
if(err)
return err;
TRACE(TRACE_INFO,"done creating static entries.");
return 0;
}
uint8_t bcast_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
uint8_t slow_proto_mac[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x01 };
uint8_t ptp_mcast_mac[] = { 0x01, 0x1b, 0x19, 0x00, 0x00, 0x00 };
hexp_port_state_t pstate;
hexp_port_list_t ports;
int i, err;
uint32_t enabled_port_mask = 0;
halexp_query_ports(&ports);
TRACE(TRACE_INFO, "Number of physical ports: %d, active ports: %d\n",
ports.num_physical_ports, ports.num_ports);
// VLAN-aware Bridge reserved addresses (802.1Q-2005 Table 8.1)
TRACE(TRACE_INFO, "adding static routes for slow protocols...");
for (i = 0; i < NUM_RESERVED_ADDR; i++) {
slow_proto_mac[5] = i;
err =
rtu_fd_create_entry(slow_proto_mac, 0,
(1 << ports.num_physical_ports), STATIC,
OVERRIDE_EXISTING);
if (err)
return err;
}
memset(port_state, 0, sizeof(port_state));
for (i = 0; i < ports.num_ports; i++) {
halexp_get_port_state(&pstate, ports.port_names[i]);
enabled_port_mask |= (1 << pstate.hw_index);
strncpy(port_state[i].if_name, ports.port_names[i], 16);
port_state[i].is_up = 0;
port_state[i].hw_index = pstate.hw_index;
port_state[i].in_use = 1;
TRACE(TRACE_INFO,
"adding static route for port %s index %d [mac %s]",
ports.port_names[i],
pstate.hw_index, mac_to_string(pstate.hw_addr)
);
err =
rtu_fd_create_entry(pstate.hw_addr, 0,
(1 << ports.num_physical_ports), STATIC,
OVERRIDE_EXISTING);
if (err)
return err;
}
// Broadcast MAC
TRACE(TRACE_INFO, "adding static route for broadcast MAC...");
err =
rtu_fd_create_entry(bcast_mac, 0,
enabled_port_mask | (1 << ports.
num_physical_ports),
STATIC, OVERRIDE_EXISTING);
err =
rtu_fd_create_entry(ptp_mcast_mac, 0,
(1 << ports.num_physical_ports), STATIC,
OVERRIDE_EXISTING);
if (err)
return err;
TRACE(TRACE_INFO, "done creating static entries.");
return 0;
}
/* Checks if the link is up on inteface (if_name). Returns non-zero if yes. */
static int check_link(int fd_raw, const char *if_name)
{
struct ifreq ifr;
struct ifreq ifr;
strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
if(ioctl(fd_raw, SIOCGIFFLAGS, &ifr) > 0) return -1;
return (ifr.ifr_flags & IFF_UP && ifr.ifr_flags & IFF_RUNNING);
strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
if (ioctl(fd_raw, SIOCGIFFLAGS, &ifr) > 0)
return -1;
return (ifr.ifr_flags & IFF_UP && ifr.ifr_flags & IFF_RUNNING);
}
static void rtu_update_ports_state()
......@@ -145,24 +153,24 @@ static void rtu_update_ports_state()
static int fd_raw = -1;
/* create a dummy socket for ioctls() to check link status on each port */
if(fd_raw < 0)
{
if (fd_raw < 0) {
fd_raw = socket(AF_PACKET, SOCK_DGRAM, 0);
if(fd_raw < 0)
return;
if (fd_raw < 0)
return;
}
for(i=0; i <= MAX_PORT; i++)
{
if(!port_state[i].in_use)
for (i = 0; i <= MAX_PORT; i++) {
if (!port_state[i].in_use)
continue;
int link_up = check_link(fd_raw, port_state[i].if_name);
if(port_state[i].is_up && !link_up)
{
TRACE(TRACE_INFO, "Port %s went down, removing corresponding entries...", port_state[i].if_name)
if (port_state[i].is_up && !link_up) {
TRACE(TRACE_INFO,
"Port %s went down, removing corresponding entries...",
port_state[i].if_name)
rtu_fd_clear_entries_for_port(port_state[i].hw_index);
rtu_fd_clear_entries_for_port(port_state[i].
hw_index);
}
port_state[i].is_up = link_up;
......@@ -177,16 +185,15 @@ static void rtu_update_ports_state()
static void *rtu_daemon_aging_process(void *arg)
{
while(1) {
rtu_update_ports_state();
rtu_fd_flush();
sleep(1);
}
while (1) {
rtu_update_ports_state();
rtu_fd_flush();
sleep(1);
}
return NULL;
return NULL;
}
/**
* \brief Handles WRIPC requests.
* Currently used to dump the filtering database contents when requested by
......@@ -195,70 +202,69 @@ static void *rtu_daemon_aging_process(void *arg)
*/
static void *rtu_daemon_wripc_process(void *arg)
{
while(1){
rtud_handle_wripc();
usleep(10000);
}
return NULL;
while (1) {
rtud_handle_wripc();
usleep(10000);
}
return NULL;
}
/**
* \brief Handles the learning process.
* @return error code
*/
static int rtu_daemon_learning_process()
{
int err, i, port_down;
struct rtu_request req; // Request read from learning queue
uint32_t port_map; // Destination port map
uint16_t vid; // VLAN identifier
while(1){
// Serve pending unrecognised request
err = rtu_read_learning_queue(&req);
if (!err) {
TRACE(
TRACE_INFO,
"ureq: port %d src %s VID %d priority %d",
req.port_id,
mac_to_string(req.src),
req.has_vid ? req.vid:0,
req.has_prio ? req.prio:0
);
for(port_down=i=0; i<=MAX_PORT;i++)
if(port_state[i].in_use && port_state[i].hw_index == req.port_id && !port_state[i].is_up)
{
port_down = 1;
break;
}
/* don't learn on ports that are down (FIFO tail?) */
if(port_down)
continue;
// If req has no VID, use 0 (untagged packet)
vid = req.has_vid ? req.vid:0;
port_map = (1 << req.port_id);
// create or update entry at filtering database
err = rtu_fd_create_entry(req.src, vid, port_map, DYNAMIC, OVERRIDE_EXISTING);
err= 0;
if (err == -ENOMEM) {
// TODO remove oldest entries (802.1D says you MAY do it)
TRACE(TRACE_INFO, "filtering database full\n");
} else if (err) {
TRACE(TRACE_INFO, "create entry: err %d\n", err);
break;
}
} else {
TRACE(TRACE_INFO,"read learning queue: err %d\n", err);
}
}
return err;
int err, i, port_down;
struct rtu_request req; // Request read from learning queue
uint32_t port_map; // Destination port map
uint16_t vid; // VLAN identifier
while (1) {
// Serve pending unrecognised request
err = rtu_read_learning_queue(&req);
if (!err) {
TRACE(TRACE_INFO,
"ureq: port %d src %s VID %d priority %d",
req.port_id,
mac_to_string(req.src),
req.has_vid ? req.vid : 0,
req.has_prio ? req.prio : 0);
for (port_down = i = 0; i <= MAX_PORT; i++)
if (port_state[i].in_use
&& port_state[i].hw_index == req.port_id
&& !port_state[i].is_up) {
port_down = 1;
break;
}
/* don't learn on ports that are down (FIFO tail?) */
if (port_down)
continue;
// If req has no VID, use 0 (untagged packet)
vid = req.has_vid ? req.vid : 0;
port_map = (1 << req.port_id);
// create or update entry at filtering database
err =
rtu_fd_create_entry(req.src, vid, port_map, DYNAMIC,
OVERRIDE_EXISTING);
err = 0;
if (err == -ENOMEM) {
// TODO remove oldest entries (802.1D says you MAY do it)
TRACE(TRACE_INFO, "filtering database full\n");
} else if (err) {
TRACE(TRACE_INFO, "create entry: err %d\n",
err);
break;
}
} else {
TRACE(TRACE_INFO, "read learning queue: err %d\n", err);
}
}
return err;
}
/**
* \brief RTU set up.
* Initialises routing table cache and RTU at hardware.
......@@ -268,51 +274,51 @@ static int rtu_daemon_learning_process()
*/
static int rtu_daemon_init(uint16_t poly, unsigned long aging_time)
{
int i, err;
// init RTU HW
TRACE(TRACE_INFO, "init rtu hardware.");
err = rtu_init();
if(err)
return err;
err = rtux_init();
if(err)
return err;
// disable RTU
TRACE(TRACE_INFO, "disable rtu.");
rtu_disable();
// init configuration for ports
TRACE(TRACE_INFO, "init port config.");
for(i = MIN_PORT; i <= MAX_PORT; i++) {
// MIN_PORT <= port <= MAX_PORT, thus no err returned
err = rtu_learn_enable_on_port(i,1);
err = rtu_pass_all_on_port(i,1);
err = rtu_pass_bpdu_on_port(i,0);
err = rtu_unset_fixed_prio_on_port(i);
err = rtu_set_unrecognised_behaviour_on_port(i, 1);
}
// init filtering database
TRACE(TRACE_INFO, "init fd.");
err = rtu_fd_init(poly, aging_time);
if (err)
return err;
// create static filtering entries
err = rtu_create_static_entries();
if(err)
return err;
// turn on RTU
TRACE(TRACE_INFO, "enable rtu.");
rtu_enable();
rtud_init_exports();
return err;
int i, err;
// init RTU HW
TRACE(TRACE_INFO, "init rtu hardware.");
err = rtu_init();
if (err)
return err;
err = rtux_init();
if (err)
return err;
// disable RTU
TRACE(TRACE_INFO, "disable rtu.");
rtu_disable();
// init configuration for ports
TRACE(TRACE_INFO, "init port config.");
for (i = MIN_PORT; i <= MAX_PORT; i++) {
// MIN_PORT <= port <= MAX_PORT, thus no err returned
err = rtu_learn_enable_on_port(i, 1);
err = rtu_pass_all_on_port(i, 1);
err = rtu_pass_bpdu_on_port(i, 0);
err = rtu_unset_fixed_prio_on_port(i);
err = rtu_set_unrecognised_behaviour_on_port(i, 1);
}
// init filtering database
TRACE(TRACE_INFO, "init fd.");
err = rtu_fd_init(poly, aging_time);
if (err)
return err;
// create static filtering entries
err = rtu_create_static_entries();
if (err)
return err;
// turn on RTU
TRACE(TRACE_INFO, "enable rtu.");
rtu_enable();
rtud_init_exports();
return err;
}
/**
......@@ -320,18 +326,19 @@ static int rtu_daemon_init(uint16_t poly, unsigned long aging_time)
*/
static void rtu_daemon_destroy()
{
// Threads stuff
pthread_cancel(wripc_process);
pthread_cancel(aging_process);
// Threads stuff
pthread_cancel(wripc_process);
pthread_cancel(aging_process);
// Turn off RTU
rtu_disable();
rtu_exit();
// Turn off RTU
rtu_disable();
rtu_exit();
}
void sigint(int signum) {
rtu_daemon_destroy();
exit(0);
void sigint(int signum)
{
rtu_daemon_destroy();
exit(0);
}
/**
......@@ -340,87 +347,87 @@ void sigint(int signum) {
int main(int argc, char **argv)
{
int op, err;
char *s, *name, *optstring;
int run_as_daemon = 0;
uint16_t poly = HW_POLYNOMIAL_CCITT; // Hash polinomial
unsigned long aging_res = DEFAULT_AGING_RES; // Aging resolution [sec.]
unsigned long aging_time = DEFAULT_AGING_TIME; // Aging time [sec.]
trace_log_stderr();
if (argc > 1) {
// Strip out path from argv[0] if exists, and extract command name
for (name = s = argv[0]; s[0]; s++) {
if (s[0] == '/' && s[1]) {
name = &s[1];
}
}
// Parse daemon options
optstring = "dhp:r:t:";
while ((op = getopt(argc, argv, optstring)) != -1) {
switch(op) {
case 'd':
run_as_daemon = 1;
break;
case 'h':
usage(name);
case 'p':
if (strcmp(optarg, "CCITT") == 0) {
poly = HW_POLYNOMIAL_CCITT;
} else if (strcmp(optarg, "IBM") == 0) {
poly = HW_POLYNOMIAL_IBM;
} else if (strcmp(optarg, "DECT") == 0) {
poly = HW_POLYNOMIAL_DECT;
} else {
fprintf(stderr, "Invalid polynomial\n");
usage(name);
}
break;
case 'r':
if ((aging_res = atol(optarg)) <= 0) {
fprintf(stderr, "Invalid aging resolution\n");
usage(name);
}
break;
case 't':
aging_time = atol(optarg);
if ((aging_time < MIN_AGING_TIME) ||
(aging_time > MAX_AGING_TIME)) {
fprintf(stderr, "Invalid aging time\n");
usage(name);
}
break;
default:
usage(name);
}
}
}
// Initialise RTU.
if((err = rtu_daemon_init(poly, aging_time)) < 0) {
rtu_daemon_destroy();
return err;
}
char *s, *name, *optstring;
int run_as_daemon = 0;
uint16_t poly = HW_POLYNOMIAL_CCITT; // Hash polinomial
unsigned long aging_res = DEFAULT_AGING_RES; // Aging resolution [sec.]
unsigned long aging_time = DEFAULT_AGING_TIME; // Aging time [sec.]
trace_log_stderr();
if (argc > 1) {
// Strip out path from argv[0] if exists, and extract command name
for (name = s = argv[0]; s[0]; s++) {
if (s[0] == '/' && s[1]) {
name = &s[1];
}
}
// Parse daemon options
optstring = "dhp:r:t:";
while ((op = getopt(argc, argv, optstring)) != -1) {
switch (op) {
case 'd':
run_as_daemon = 1;
break;
case 'h':
usage(name);
case 'p':
if (strcmp(optarg, "CCITT") == 0) {
poly = HW_POLYNOMIAL_CCITT;
} else if (strcmp(optarg, "IBM") == 0) {
poly = HW_POLYNOMIAL_IBM;
} else if (strcmp(optarg, "DECT") == 0) {
poly = HW_POLYNOMIAL_DECT;
} else {
fprintf(stderr, "Invalid polynomial\n");
usage(name);
}
break;
case 'r':
if ((aging_res = atol(optarg)) <= 0) {
fprintf(stderr,
"Invalid aging resolution\n");
usage(name);
}
break;
case 't':
aging_time = atol(optarg);
if ((aging_time < MIN_AGING_TIME) ||
(aging_time > MAX_AGING_TIME)) {
fprintf(stderr, "Invalid aging time\n");
usage(name);
}
break;
default:
usage(name);
}
}
}
// Initialise RTU.
if ((err = rtu_daemon_init(poly, aging_time)) < 0) {
rtu_daemon_destroy();
return err;
}
// Register signal handler
signal(SIGINT, sigint);
// daemonize _before_ creating threads
if(run_as_daemon)
daemonize();
// Start up aging process and auxiliary WRIPC thread
if ((err = pthread_create(&aging_process, NULL, rtu_daemon_aging_process, (void *) aging_res)) ||
(err = pthread_create(&wripc_process, NULL, rtu_daemon_wripc_process, NULL))) {
rtu_daemon_destroy();
return err;
}
// Start up learning process.
err = rtu_daemon_learning_process();
// On error, release RTU resources
rtu_daemon_destroy();
// daemonize _before_ creating threads
if (run_as_daemon)
daemonize();
// Start up aging process and auxiliary WRIPC thread
if ((err =
pthread_create(&aging_process, NULL, rtu_daemon_aging_process,
(void *)aging_res))
|| (err =
pthread_create(&wripc_process, NULL, rtu_daemon_wripc_process,
NULL))) {
rtu_daemon_destroy();
return err;
}
// Start up learning process.
err = rtu_daemon_learning_process();
// On error, release RTU resources
rtu_daemon_destroy();
return err;
}
......@@ -26,7 +26,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
......@@ -49,23 +48,20 @@ static struct minipc_ch *rtud_ch;
#define MINIPC_EXP_FUNC(stru,func) stru.f= func; \
if (minipc_export(rtud_ch, &stru) < 0) { TRACE(TRACE_FATAL,"Could not export %s (rtu_ch=%d)",stru.name,rtud_ch); }
/* The exported function */
int rtudexp_get_fd_list(const struct minipc_pd *pd,
uint32_t *args, void *ret)
int rtudexp_get_fd_list(const struct minipc_pd *pd, uint32_t * args, void *ret)
{
int i;
rtudexp_fd_list_t *list = ret;
int start_from = args[0];
TRACE(TRACE_INFO, "GetFDList start=%d", start_from);
TRACE(TRACE_INFO,"GetFDList start=%d",start_from);
for(i=0;i<8;i++)
{
struct filtering_entry *ent = rtu_fd_lookup_htab_entry(start_from + i);
if(!ent) break;
for (i = 0; i < 8; i++) {
struct filtering_entry *ent =
rtu_fd_lookup_htab_entry(start_from + i);
if (!ent)
break;
memcpy(list->list[i].mac, ent->mac, sizeof(ent->mac));
//printf("Ent: %s %x\n", mac_to_string(ent->mac), ent->port_mask_dst);
......@@ -81,82 +77,77 @@ int rtudexp_get_fd_list(const struct minipc_pd *pd,
}
list->num_rules = i;
list->next = (i < 8 ? 0 : start_from+i);
list->next = (i < 8 ? 0 : start_from + i);
return 0;
}
/* The exported vlan */
int rtudexp_get_vd_list(const struct minipc_pd *pd,
uint32_t *args, void *ret)
int rtudexp_get_vd_list(const struct minipc_pd *pd, uint32_t * args, void *ret)
{
int i = 0;
rtudexp_vd_list_t *list = ret;
int current = args[0];
TRACE(TRACE_INFO,"GetVDList start=%d",current);
do
{
struct vlan_table_entry *ent = rtu_vlan_entry_get(current);
if(!ent) break;
if(ent->drop == 0 || ent->port_mask != 0x0)
{
list->list[i].vid = current;
list->list[i].port_mask = ent->port_mask;
list->list[i].drop = ent->drop;
list->list[i].fid = ent->fid;
list->list[i].has_prio = ent->has_prio;
list->list[i].prio_override = ent->prio_override;
list->list[i].prio = ent->prio;
TRACE(TRACE_INFO, "vlan_entry_vd: vid %d, drop=%d, fid=%d, port_mask 0x%x",
list->list[i].vid ,
list->list[i].drop,
list->list[i].fid,
list->list[i].port_mask
);
i++;
TRACE(TRACE_INFO, "GetVDList start=%d", current);
do {
struct vlan_table_entry *ent = rtu_vlan_entry_get(current);
if (!ent)
break;
if (ent->drop == 0 || ent->port_mask != 0x0) {
list->list[i].vid = current;
list->list[i].port_mask = ent->port_mask;
list->list[i].drop = ent->drop;
list->list[i].fid = ent->fid;
list->list[i].has_prio = ent->has_prio;
list->list[i].prio_override = ent->prio_override;
list->list[i].prio = ent->prio;
TRACE(TRACE_INFO,
"vlan_entry_vd: vid %d, drop=%d, fid=%d, port_mask 0x%x",
list->list[i].vid, list->list[i].drop,
list->list[i].fid, list->list[i].port_mask);
i++;
}
current++;
if(current == NUM_VLANS) break;
} while(i < 8);
if (current == NUM_VLANS)
break;
} while (i < 8);
list->num_entries = i;
list->next = (i < 8 ? 0 : current);
return 0;
}
int rtudexp_clear_entries(const struct minipc_pd *pd,
uint32_t *args, void *ret)
uint32_t * args, void *ret)
{
int iface_num=(int)args[0];
int force=(int)args[1];
int *p_ret=(int*)ret; //force pointed to int type
int iface_num = (int)args[0];
int force = (int)args[1];
int *p_ret = (int *)ret; //force pointed to int type
TRACE(TRACE_INFO,"iface=%d, force=%d",iface_num,force);
TRACE(TRACE_INFO, "iface=%d, force=%d", iface_num, force);
//Do nothing
if(force) TRACE(TRACE_INFO,"wr%d > force %d is not implemented",iface_num,force);
if (force)
TRACE(TRACE_INFO, "wr%d > force %d is not implemented",
iface_num, force);
rtu_fd_clear_entries_for_port(iface_num);
*p_ret=0;
*p_ret = 0;
return *p_ret;
}
int rtudexp_add_entry(const struct minipc_pd *pd,
uint32_t *args, void *ret)
int rtudexp_add_entry(const struct minipc_pd *pd, uint32_t * args, void *ret)
{
uint8_t mac_tmp[ETH_ALEN] = {0};
uint8_t mac_tmp[ETH_ALEN] = { 0 };
hexp_port_list_t ports;
char *strEHA;
int port, mode;
int *p_ret=(int*)ret; //force pointed to int type
int *p_ret = (int *)ret; //force pointed to int type
strEHA = (char *)args;
args = minipc_get_next_arg(args, pd->args[0]);
......@@ -167,30 +158,33 @@ int rtudexp_add_entry(const struct minipc_pd *pd,
halexp_query_ports(&ports);
if(mac_from_str(mac_tmp,strEHA)!=ETH_ALEN)
TRACE(TRACE_ERROR,"%s is an invalid MAC format (XX:XX:XX:XX:XX:XX)",strEHA);
if (mac_from_str(mac_tmp, strEHA) != ETH_ALEN)
TRACE(TRACE_ERROR,
"%s is an invalid MAC format (XX:XX:XX:XX:XX:XX)",
strEHA);
TRACE(TRACE_INFO,"Create entry for (MAC=%s) port %x, mode:%s",mac_to_string(mac_tmp),1 << port,(mode)?"DYNAMIC":"STATIC");
*p_ret=rtu_fd_create_entry(mac_tmp, 0, 1 << port, mode, OVERRIDE_EXISTING);
TRACE(TRACE_INFO, "Create entry for (MAC=%s) port %x, mode:%s",
mac_to_string(mac_tmp), 1 << port, (mode) ? "DYNAMIC" : "STATIC");
*p_ret =
rtu_fd_create_entry(mac_tmp, 0, 1 << port, mode, OVERRIDE_EXISTING);
return *p_ret;
}
int rtudexp_vlan_entry(const struct minipc_pd *pd,
uint32_t *args, void *ret)
int rtudexp_vlan_entry(const struct minipc_pd *pd, uint32_t * args, void *ret)
{
int vid, fid, mask, drop, prio, has_prio, prio_override;
int *p_ret=(int*)ret; //force pointed to int type
int *p_ret = (int *)ret; //force pointed to int type
*p_ret = 0;
vid = (int)args[0];
fid = (int)args[1];
mask= (int)args[2];
drop= (int)args[3];
prio= (int)args[4];
has_prio= (int)args[5];
prio_override= (int)args[6];
rtu_fd_create_vlan_entry(vid, (uint32_t)mask, (uint8_t)fid, (uint8_t)prio, has_prio,prio_override, drop);
vid = (int)args[0];
fid = (int)args[1];
mask = (int)args[2];
drop = (int)args[3];
prio = (int)args[4];
has_prio = (int)args[5];
prio_override = (int)args[6];
rtu_fd_create_vlan_entry(vid, (uint32_t) mask, (uint8_t) fid,
(uint8_t) prio, has_prio, prio_override, drop);
return *p_ret;
}
......@@ -198,17 +192,17 @@ int rtud_init_exports()
{
rtud_ch = minipc_server_create("rtud", 0);
if(!rtud_ch < 0)
if (!rtud_ch < 0)
return -1;
TRACE(TRACE_INFO,"wripc server created [fd %d]",
minipc_fileno(rtud_ch));
TRACE(TRACE_INFO, "wripc server created [fd %d]",
minipc_fileno(rtud_ch));
MINIPC_EXP_FUNC(rtud_export_get_fd_list,rtudexp_get_fd_list);
MINIPC_EXP_FUNC(rtud_export_get_vd_list,rtudexp_get_vd_list);
MINIPC_EXP_FUNC(rtud_export_clear_entries,rtudexp_clear_entries);
MINIPC_EXP_FUNC(rtud_export_add_entry,rtudexp_add_entry);
MINIPC_EXP_FUNC(rtud_export_vlan_entry,rtudexp_vlan_entry);
MINIPC_EXP_FUNC(rtud_export_get_fd_list, rtudexp_get_fd_list);
MINIPC_EXP_FUNC(rtud_export_get_vd_list, rtudexp_get_vd_list);
MINIPC_EXP_FUNC(rtud_export_clear_entries, rtudexp_clear_entries);
MINIPC_EXP_FUNC(rtud_export_add_entry, rtudexp_add_entry);
MINIPC_EXP_FUNC(rtud_export_vlan_entry, rtudexp_vlan_entry);
return 0;
}
......
......@@ -25,27 +25,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RTUD_EXPORTS_H
#define __RTUD_EXPORTS_H
#include <stdint.h>
#include <minipc.h>
typedef struct
{
uint8_t mac[8];
uint32_t dpm;
uint32_t spm;
uint8_t priority;
int dynamic;
uint16_t hash;
int bucket;
int age;
int fid;
typedef struct {
uint8_t mac[8];
uint32_t dpm;
uint32_t spm;
uint8_t priority;
int dynamic;
uint16_t hash;
int bucket;
int age;
int fid;
} rtudexp_fd_entry_t;
typedef struct {
typedef struct {
rtudexp_fd_entry_t list[8];
int num_rules;
......@@ -53,34 +51,32 @@ typedef struct {
} rtudexp_fd_list_t;
///// VLAN export
typedef struct
{
int vid;
uint32_t port_mask;
uint8_t fid;
uint8_t prio;
int has_prio;
int prio_override;
int drop;
typedef struct {
int vid;
uint32_t port_mask;
uint8_t fid;
uint8_t prio;
int has_prio;
int prio_override;
int drop;
} rtudexp_vd_entry_t;
typedef struct {
typedef struct {
rtudexp_vd_entry_t list[8];
int num_entries;
int next;
} rtudexp_vd_list_t;
/* Export this function: it returns a structure */
struct minipc_pd rtud_export_get_fd_list = {
.name = "get_fd_list",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRUCT,
rtudexp_fd_list_t),
.args = {
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_END,
},
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_END,
},
};
/* Export this function: it returns a structure */
struct minipc_pd rtud_export_get_vd_list = {
......@@ -88,49 +84,48 @@ struct minipc_pd rtud_export_get_vd_list = {
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRUCT,
rtudexp_vd_list_t),
.args = {
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_END,
},
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_END,
},
};
/* Export of a function to set remove entry in rtu */
struct minipc_pd rtud_export_clear_entries = {
.name = "clear_entries",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT,int),
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
.args = {
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_END,
},
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_END,
},
};
/* Export of a function to add entry in rtu */
struct minipc_pd rtud_export_add_entry = {
.name = "add_entry",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT,int),
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
.args = {
MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRING,char *),
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_END,
},
MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRING, char *),
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_END,
},
};
/* Export of a function to add vlan entry in rtu */
struct minipc_pd rtud_export_vlan_entry = {
.name = "vlan_entry",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT,int),
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
.args = {
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 0: vid
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 1: fid
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 2: mask
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 3: drop
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 4: prio
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 5: has_prio
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 6: prio_override
MINIPC_ARG_END,
},
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 0: vid
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 1: fid
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 2: mask
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 3: drop
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 4: prio
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 5: has_prio
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), // 6: prio_override
MINIPC_ARG_END,
},
};
#endif
......@@ -26,7 +26,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -38,54 +37,55 @@
void daemonize(void)
{
pid_t pid, sid;
pid_t pid, sid;
/* already a daemon */
if ( getppid() == 1 ) return;
/* already a daemon */
if (getppid() == 1)
return;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
/* At this point we are executing as the child process */
/* At this point we are executing as the child process */
/* Change the file mode mask */
umask(0);
/* Change the file mode mask */
umask(0);
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
exit(EXIT_FAILURE);
}
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
exit(EXIT_FAILURE);
}
/* Change the current working directory. This prevents the current
directory from being locked; hence not being able to remove it. */
if ((chdir("/")) < 0) {
exit(EXIT_FAILURE);
}
/* Change the current working directory. This prevents the current
directory from being locked; hence not being able to remove it. */
if ((chdir("/")) < 0) {
exit(EXIT_FAILURE);
}
/* Redirect standard files to /dev/null */
freopen( "/dev/null", "r", stdin);
freopen( "/dev/null", "w", stdout);
freopen( "/dev/null", "w", stderr);
/* Redirect standard files to /dev/null */
freopen("/dev/null", "r", stdin);
freopen("/dev/null", "w", stdout);
freopen("/dev/null", "w", stderr);
}
void usage(char *name)
{
fprintf(stderr,
"Usage: %s [-dh] [-p <polly>] [-r <time>] [-t <time>]\n"
"\t-d daemonize\n"
"\t-h help\n"
"\t-p polynomial for hash calculation. Possible values are CCITT, IBM, DECT\n"
"\t-r aging resolution (in sec). 20 sec by default\n"
"\t-t aging time (10 to 10000 sec). 300 sec by default.\n",
name);
exit(1);
fprintf(stderr,
"Usage: %s [-dh] [-p <polly>] [-r <time>] [-t <time>]\n"
"\t-d daemonize\n"
"\t-h help\n"
"\t-p polynomial for hash calculation. Possible values are CCITT, IBM, DECT\n"
"\t-r aging resolution (in sec). 20 sec by default\n"
"\t-t aging time (10 to 10000 sec). 300 sec by default.\n",
name);
exit(1);
}
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