Commit d52fdb87 authored by Alessandro Rubini's avatar Alessandro Rubini

tools/pfilter-builder: completed

This changes pfilter-builder.c so it really build in user space, but removing
register setting and creating output files instead.

Running this program creates 3 files, that correspond to the previous
three #ifdef conditions.  The files are:

      rules-plain.bin    this is used for the no-etherbone configuration
      rules-ebone.bin    etherbone setup
      rules-e+nic.bin    etherbon plus 7solution's wr-nic packet filter

The files begin with a magix 0x11223344 word, that allows the soft-core
to fix any endianness difference (so no hairy mishaps are expected when
switching to a different soft-core). Then the 40-bit command words are
saved as 64-bit vaules, LSB-first. The output file is thus an odd number
of words and no 64-bit alignment is required.

The first three instructions of the packet filter are used to compare
the destination mac address of the frame.  We now use a fake mac address,
and the LM32 code will change it while programming the binary.

Please look at this commit while ignoring white-space, as it changes
indentation while turning #ifdef/#else into if()/else .
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent c9930892
...@@ -8,3 +8,4 @@ eb-w1-write ...@@ -8,3 +8,4 @@ eb-w1-write
sdb-wrpc.bin sdb-wrpc.bin
flash-read flash-read
flash-write flash-write
pfilter-builder
...@@ -5,6 +5,7 @@ CFLAGS = -Wall -ggdb -I../include ...@@ -5,6 +5,7 @@ CFLAGS = -Wall -ggdb -I../include
LDFLAGS = -lutil LDFLAGS = -lutil
ALL = genraminit genramvhd genrammif wrpc-uart-sw ALL = genraminit genramvhd genrammif wrpc-uart-sw
ALL += wrpc-w1-read wrpc-w1-write ALL += wrpc-w1-read wrpc-w1-write
ALL += pfilter-builder
ifneq ($(EB),no) ifneq ($(EB),no)
ALL += eb-w1-write ALL += eb-w1-write
......
...@@ -108,14 +108,18 @@ ...@@ -108,14 +108,18 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "board.h" #include <endpoint.h> /* for operations and type pfilter_op_t */
#include <endpoint.h>
#include <hw/endpoint_regs.h>
#define PFILTER_MAX_CODE_SIZE 32 #define PFILTER_MAX_CODE_SIZE 32
#define pfilter_dbg pp_printf #define pfilter_dbg printf
char *prgname;
extern volatile struct EP_WB *EP; extern volatile struct EP_WB *EP;
...@@ -256,35 +260,45 @@ static void pfilter_logic3(int rd, int ra, pfilter_op_t op, int rb, ...@@ -256,35 +260,45 @@ static void pfilter_logic3(int rd, int ra, pfilter_op_t op, int rb,
code_buf[code_pos++] = ir; code_buf[code_pos++] = ir;
} }
/* Terminates the microcode, loads it to the endpoint and enables the pfilter */ /* Terminates the microcode, creating the output file */
static void pfilter_load() static void pfilter_output(char *fname)
{ {
uint32_t v1, v2;
int i; int i;
FILE *f;
code_buf[code_pos++] = (1ULL << 35); // insert FIN instruction code_buf[code_pos++] = (1ULL << 35); // insert FIN instruction
EP->PFCR0 = 0; // disable pfilter f = fopen(fname, "w");
if (!f) {
fprintf(stderr, "%s: %s: %s\n", prgname, fname, strerror(errno));
exit(1);
}
/* First write a magic word, so the target can check endianness */
v1 = 0x11223344;
fwrite(&v1, sizeof(v1), 1, f);
pfilter_dbg("Writing \"%s\"\n", fname);
for (i = 0; i < code_pos; i++) { for (i = 0; i < code_pos; i++) {
pfilter_dbg("pos %02i: %x.%08x\n", i, (uint32_t)(code_buf[i] >> 32), (uint32_t)(code_buf[i])); pfilter_dbg(" pos %02i: %x.%08x\n", i,
uint32_t cr0, cr1; (uint32_t)(code_buf[i] >> 32),
cr1 = EP_PFCR1_MM_DATA_LSB_W(code_buf[i] & 0xfff); (uint32_t)(code_buf[i]));
cr0 = /* Explicitly write the LSB first */
EP_PFCR0_MM_ADDR_W(i) | EP_PFCR0_MM_DATA_MSB_W(code_buf[i] v1 = code_buf[i];
>> 12) | v2 = code_buf[i] >> 32;
EP_PFCR0_MM_WRITE_MASK; fwrite(&v1, sizeof(v1), 1, f);
fwrite(&v2, sizeof(v2), 1, f);
EP->PFCR1 = cr1;
EP->PFCR0 = cr0;
} }
fclose(f);
EP->PFCR0 = EP_PFCR0_ENABLE;
} }
/* sample packet filter initialization: /* We generate all supported rule-sets, those that used to be ifdef'd */
- redirects broadcasts and PTP packets to the WR Core #define MODE_ETHERBONE 1
- redirects unicasts addressed to self with ethertype 0xa0a0 to the external fabric */ #define MODE_NIC_PFILTER 2
void pfilter_init_default() void pfilter_init(int mode, char *fname)
{ {
pfilter_new(); pfilter_new();
pfilter_nop(); pfilter_nop();
...@@ -293,9 +307,9 @@ void pfilter_init_default() ...@@ -293,9 +307,9 @@ void pfilter_init_default()
* Make three sets of comparisons over the destination address. * Make three sets of comparisons over the destination address.
* After these 9 instructions, the whole Eth header is available. * After these 9 instructions, the whole Eth header is available.
*/ */
pfilter_cmp(0, EP->MACH & 0xffff, 0xffff, MOV, FRAME_OUR_MAC); pfilter_cmp(0, 0x1234, 0xffff, MOV, FRAME_OUR_MAC); /* Use fake MAC: 12:34:56:78:9a:bc */
pfilter_cmp(1, EP->MACL >> 16, 0xffff, AND, FRAME_OUR_MAC); pfilter_cmp(1, 0x5678, 0xffff, AND, FRAME_OUR_MAC);
pfilter_cmp(2, EP->MACL & 0xffff, 0xffff, AND, FRAME_OUR_MAC); /* set when our MAC */ pfilter_cmp(2, 0x9abc, 0xffff, AND, FRAME_OUR_MAC); /* set when our MAC */
pfilter_cmp(0, 0xffff, 0xffff, MOV, FRAME_BROADCAST); pfilter_cmp(0, 0xffff, 0xffff, MOV, FRAME_BROADCAST);
pfilter_cmp(1, 0xffff, 0xffff, AND, FRAME_BROADCAST); pfilter_cmp(1, 0xffff, 0xffff, AND, FRAME_BROADCAST);
...@@ -315,54 +329,64 @@ void pfilter_init_default() ...@@ -315,54 +329,64 @@ void pfilter_init_default()
pfilter_cmp(11, 0x0001, 0x00ff, MOV, FRAME_ICMP); pfilter_cmp(11, 0x0001, 0x00ff, MOV, FRAME_ICMP);
pfilter_cmp(11, 0x0011, 0x00ff, MOV, FRAME_UDP); pfilter_cmp(11, 0x0011, 0x00ff, MOV, FRAME_UDP);
#ifdef CONFIG_ETHERBONE if (mode & MODE_ETHERBONE) {
/* Mark bits for unicast to us, and for unicast-to-us-or-broadcast */ /* Mark bits for unicast to us, and for unicast-to-us-or-broadcast */
pfilter_logic3(FRAME_IP_UNI, FRAME_OUR_MAC, OR, R_ZERO, AND, FRAME_TYPE_IPV4); pfilter_logic3(FRAME_IP_UNI, FRAME_OUR_MAC, OR, R_ZERO, AND, FRAME_TYPE_IPV4);
pfilter_logic3(FRAME_IP_OK, FRAME_BROADCAST, OR, FRAME_OUR_MAC, AND, FRAME_TYPE_IPV4); pfilter_logic3(FRAME_IP_OK, FRAME_BROADCAST, OR, FRAME_OUR_MAC, AND, FRAME_TYPE_IPV4);
/* Make a selection for the CPU, that is later still added-to */ /* Make a selection for the CPU, that is later still added-to */
pfilter_logic3(R_TMP, FRAME_BROADCAST, AND, FRAME_TYPE_ARP, OR, FRAME_TYPE_PTP2); pfilter_logic3(R_TMP, FRAME_BROADCAST, AND, FRAME_TYPE_ARP, OR, FRAME_TYPE_PTP2);
pfilter_logic3(FRAME_FOR_CPU, FRAME_IP_UNI, AND, FRAME_ICMP, OR, R_TMP); pfilter_logic3(FRAME_FOR_CPU, FRAME_IP_UNI, AND, FRAME_ICMP, OR, R_TMP);
/* Ethernet = 14 bytes, IPv4 = 20 bytes, offset to dport: 2 = 36/2 = 18 */ /* Ethernet = 14 bytes, IPv4 = 20 bytes, offset to dport: 2 = 36/2 = 18 */
pfilter_cmp(18, 0x0044, 0xffff, MOV, R_TMP); /* R_TMP now means dport = BOOTPC */ pfilter_cmp(18, 0x0044, 0xffff, MOV, R_TMP); /* R_TMP now means dport = BOOTPC */
pfilter_logic3(R_TMP, R_TMP, AND, FRAME_UDP, AND, FRAME_IP_OK); /* BOOTPC and UDP and IP(unicast|broadcast) */ pfilter_logic3(R_TMP, R_TMP, AND, FRAME_UDP, AND, FRAME_IP_OK); /* BOOTPC and UDP and IP(unicast|broadcast) */
pfilter_logic2(FRAME_FOR_CPU, R_TMP, OR, FRAME_FOR_CPU); pfilter_logic2(FRAME_FOR_CPU, R_TMP, OR, FRAME_FOR_CPU);
#ifdef CONFIG_NIC_PFILTER if (mode & MODE_NIC_PFILTER) {
pfilter_cmp(18,0xebd0,0xffff,MOV, FRAME_PORT_ETHERBONE); pfilter_cmp(18,0xebd0,0xffff,MOV, FRAME_PORT_ETHERBONE);
/* Here we had a commented-out check for magic (offset 21, value 0x4e6f) */ /* Here we had a commented-out check for magic (offset 21, value 0x4e6f) */
pfilter_logic2(R_CLASS(0), FRAME_FOR_CPU, MOV, R_ZERO); pfilter_logic2(R_CLASS(0), FRAME_FOR_CPU, MOV, R_ZERO);
pfilter_logic2(R_CLASS(5), FRAME_PORT_ETHERBONE, OR, R_ZERO); /* class 5: Etherbone packet => Etherbone Core */ pfilter_logic2(R_CLASS(5), FRAME_PORT_ETHERBONE, OR, R_ZERO); /* class 5: Etherbone packet => Etherbone Core */
pfilter_logic3(R_CLASS(7), FRAME_FOR_CPU, OR, FRAME_PORT_ETHERBONE, NOT, R_ZERO); /* class 7: Rest => NIC Core */ pfilter_logic3(R_CLASS(7), FRAME_FOR_CPU, OR, FRAME_PORT_ETHERBONE, NOT, R_ZERO); /* class 7: Rest => NIC Core */
} else {
#else pfilter_logic3(R_TMP, FRAME_IP_OK, AND, FRAME_UDP, OR, FRAME_FOR_CPU); /* Something we accept: cpu+udp or streamer */
pfilter_logic3(R_TMP, FRAME_IP_OK, AND, FRAME_UDP, OR, FRAME_FOR_CPU); /* Something we accept: cpu+udp or streamer */
pfilter_logic3(R_DROP, R_TMP, OR, FRAME_TYPE_STREAMER, NOT, R_ZERO); /* None match? drop */ pfilter_logic3(R_DROP, R_TMP, OR, FRAME_TYPE_STREAMER, NOT, R_ZERO); /* None match? drop */
pfilter_logic2(R_CLASS(7), FRAME_IP_OK, AND, FRAME_UDP); /* class 7: UDP/IP(unicast|broadcast) => external fabric */ pfilter_logic2(R_CLASS(7), FRAME_IP_OK, AND, FRAME_UDP); /* class 7: UDP/IP(unicast|broadcast) => external fabric */
pfilter_logic2(R_CLASS(6), FRAME_BROADCAST, AND, FRAME_TYPE_STREAMER); /* class 6: streamer broadcasts => external fabric */ pfilter_logic2(R_CLASS(6), FRAME_BROADCAST, AND, FRAME_TYPE_STREAMER); /* class 6: streamer broadcasts => external fabric */
pfilter_logic2(R_CLASS(0), FRAME_FOR_CPU, MOV, R_ZERO); /* class 0: all selected for CPU earlier */ pfilter_logic2(R_CLASS(0), FRAME_FOR_CPU, MOV, R_ZERO); /* class 0: all selected for CPU earlier */
#endif }
} else { /* not etherbone */
#else pfilter_logic3(FRAME_PTP_OK, FRAME_OUR_MAC, OR, FRAME_PTP_MCAST, AND, FRAME_TYPE_PTP2);
pfilter_logic3(FRAME_PTP_OK, FRAME_OUR_MAC, OR, FRAME_PTP_MCAST, AND, FRAME_TYPE_PTP2); pfilter_logic2(FRAME_STREAMER_BCAST, FRAME_BROADCAST, AND, FRAME_TYPE_STREAMER);
pfilter_logic2(FRAME_STREAMER_BCAST, FRAME_BROADCAST, AND, FRAME_TYPE_STREAMER); pfilter_logic3(R_TMP, FRAME_PTP_OK, OR, FRAME_STREAMER_BCAST, NOT, R_ZERO); /* R_TMP = everything else */
pfilter_logic3(R_TMP, FRAME_PTP_OK, OR, FRAME_STREAMER_BCAST, NOT, R_ZERO); /* R_TMP = everything else */
pfilter_logic2(R_CLASS(7), R_TMP, MOV, R_ZERO); /* class 7: all non PTP and non-streamer traffic => external fabric */ pfilter_logic2(R_CLASS(7), R_TMP, MOV, R_ZERO); /* class 7: all non PTP and non-streamer traffic => external fabric */
pfilter_logic2(R_CLASS(6), FRAME_STREAMER_BCAST, MOV, R_ZERO); /* class 6: streamer broadcasts => external fabric */ pfilter_logic2(R_CLASS(6), FRAME_STREAMER_BCAST, MOV, R_ZERO); /* class 6: streamer broadcasts => external fabric */
pfilter_logic2(R_CLASS(0), FRAME_PTP_OK, MOV, R_ZERO); /* class 0: PTP frames => LM32 */ pfilter_logic2(R_CLASS(0), FRAME_PTP_OK, MOV, R_ZERO); /* class 0: PTP frames => LM32 */
#endif }
pfilter_output(fname);
pfilter_load(); }
int main(int argc, char **argv) /* no arguments used currently */
{
prgname = argv[0];
pfilter_init(0, "rules-plain.bin");
pfilter_init(MODE_ETHERBONE, "rules-ebone.bin");
pfilter_init(MODE_ETHERBONE | MODE_NIC_PFILTER, "rules-e+nic.bin");
exit(0);
} }
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