diff --git a/boards/arria/board.h b/boards/arria/board.h index 87cc6cb041bc8f8e97971bcf733553c1dfaf2174..39b2948f6b5d2c3ecf7d9f84eb9ef0d2d876cc29 100644 --- a/boards/arria/board.h +++ b/boards/arria/board.h @@ -6,7 +6,7 @@ /* Board-specific parameters */ /* WR Core system/CPU clock frequency in Hz */ -#define CPU_CLOCK 62500000ULL +#define CPU_CLOCK 125000000ULL /* WR Reference clock period (picoseconds) and frequency (Hz) */ #define REF_CLOCK_PERIOD_PS 8000 @@ -19,7 +19,7 @@ #define NET_MAX_SOCKETS 3 /* Socket buffer size, determines the max. RX packet size */ -#define NET_SKBUF_SIZE 256 +#define NET_SKBUF_SIZE 512 /* Number of auxillary clock channels - usually equal to the number of FMCs */ #define NUM_AUX_CLOCKS 1 diff --git a/lib/arp.c b/lib/arp.c index 5593ffe3b6a61dcf5a31abc712630240bca1aa19..a8a459e6b7c16a18f5699d3b0013ce7f946a7a6c 100644 --- a/lib/arp.c +++ b/lib/arp.c @@ -72,6 +72,8 @@ void arp_poll(void) { wr_sockaddr_t addr; int len; + if (needIP) return; /* can't do ARP w/o an address... */ + if ((len = ptpd_netif_recvfrom(arp_socket, &addr, buf, sizeof(buf), 0)) > 0) if ((len = process_arp(buf, len)) > 0) ptpd_netif_sendto(arp_socket, &addr, buf, len, 0); diff --git a/lib/bootp.c b/lib/bootp.c new file mode 100644 index 0000000000000000000000000000000000000000..38d4162107ae4e376c80d96f2faea8f3bbaf8da2 --- /dev/null +++ b/lib/bootp.c @@ -0,0 +1,144 @@ +#include <string.h> + +#include "ipv4.h" + +#define IP_VERSION 0 +#define IP_TOS (IP_VERSION+1) +#define IP_LEN (IP_TOS+1) +#define IP_ID (IP_LEN+2) +#define IP_FLAGS (IP_ID+2) +#define IP_TTL (IP_FLAGS+2) +#define IP_PROTOCOL (IP_TTL+1) +#define IP_CHECKSUM (IP_PROTOCOL+1) +#define IP_SOURCE (IP_CHECKSUM+2) +#define IP_DEST (IP_SOURCE+4) +#define IP_END (IP_DEST+4) + +#define UDP_VIRT_SADDR (IP_END-12) +#define UDP_VIRT_DADDR (UDP_VIRT_SADDR+4) +#define UDP_VIRT_ZEROS (UDP_VIRT_DADDR+4) +#define UDP_VIRT_PROTO (UDP_VIRT_ZEROS+1) +#define UDP_VIRT_LENGTH (UDP_VIRT_PROTO+1) + +#define UDP_SPORT (IP_END) +#define UDP_DPORT (UDP_SPORT+2) +#define UDP_LENGTH (UDP_DPORT+2) +#define UDP_CHECKSUM (UDP_LENGTH+2) +#define UDP_END (UDP_CHECKSUM+2) + +#define BOOTP_OP (UDP_END) +#define BOOTP_HTYPE (BOOTP_OP+1) +#define BOOTP_HLEN (BOOTP_HTYPE+1) +#define BOOTP_HOPS (BOOTP_HLEN+1) +#define BOOTP_XID (BOOTP_HOPS+1) +#define BOOTP_SECS (BOOTP_XID+4) +#define BOOTP_UNUSED (BOOTP_SECS+2) +#define BOOTP_CIADDR (BOOTP_UNUSED+2) +#define BOOTP_YIADDR (BOOTP_CIADDR+4) +#define BOOTP_SIADDR (BOOTP_YIADDR+4) +#define BOOTP_GIADDR (BOOTP_SIADDR+4) +#define BOOTP_CHADDR (BOOTP_GIADDR+4) +#define BOOTP_SNAME (BOOTP_CHADDR+16) +#define BOOTP_FILE (BOOTP_SNAME+64) +#define BOOTP_VEND (BOOTP_FILE+128) +#define BOOTP_END (BOOTP_VEND+64) + +int send_bootp(uint8_t* buf, int retry) { + unsigned short sum; + + // ----------- BOOTP ------------ + buf[BOOTP_OP] = 1; /* bootrequest */ + buf[BOOTP_HTYPE] = 1; /* ethernet */ + buf[BOOTP_HLEN] = 6; /* MAC length */ + buf[BOOTP_HOPS] = 0; + + /* A unique identifier for the request !!! FIXME */ + get_mac_addr(buf+BOOTP_XID); + buf[BOOTP_XID+0] ^= buf[BOOTP_XID+4]; + buf[BOOTP_XID+1] ^= buf[BOOTP_XID+5]; + buf[BOOTP_XID+2] ^= (retry >> 8) & 0xFF; + buf[BOOTP_XID+3] ^= retry & 0xFF; + + buf[BOOTP_SECS] = (retry >> 8) & 0xFF; + buf[BOOTP_SECS+1] = retry & 0xFF; + memset(buf+BOOTP_UNUSED, 0, 2); + + memset(buf+BOOTP_CIADDR, 0, 4); /* own IP if known */ + memset(buf+BOOTP_YIADDR, 0, 4); + memset(buf+BOOTP_SIADDR, 0, 4); + memset(buf+BOOTP_GIADDR, 0, 4); + + memset(buf+BOOTP_CHADDR, 0, 16); + get_mac_addr(buf+BOOTP_CHADDR); /* own MAC address */ + + memset(buf+BOOTP_SNAME, 0, 64); /* desired BOOTP server */ + memset(buf+BOOTP_FILE, 0, 128); /* desired BOOTP file */ + memset(buf+BOOTP_VEND, 0, 64); /* vendor extensions */ + + // ------------ UDP ------------- + memset(buf+UDP_VIRT_SADDR, 0, 4); + memset(buf+UDP_VIRT_DADDR, 0xFF, 4); + buf[UDP_VIRT_ZEROS] = 0; + buf[UDP_VIRT_PROTO] = 0x11; /* UDP */ + buf[UDP_VIRT_LENGTH] = (BOOTP_END-IP_END) >> 8; + buf[UDP_VIRT_LENGTH+1] = (BOOTP_END-IP_END) & 0xff; + + buf[UDP_SPORT] = 0; + buf[UDP_SPORT+1] = 68; /* BOOTP client */ + buf[UDP_DPORT] = 0; + buf[UDP_DPORT+1] = 67; /* BOOTP server */ + buf[UDP_LENGTH] = (BOOTP_END-IP_END) >> 8; + buf[UDP_LENGTH+1] = (BOOTP_END-IP_END) & 0xff; + buf[UDP_CHECKSUM] = 0; + buf[UDP_CHECKSUM+1] = 0; + + sum = ipv4_checksum((unsigned short*)(buf+UDP_VIRT_SADDR), (BOOTP_END-UDP_VIRT_SADDR)/2); + if (sum == 0) sum = 0xFFFF; + + buf[UDP_CHECKSUM+0] = (sum >> 8); + buf[UDP_CHECKSUM+1] = sum & 0xff; + + // ------------ IP -------------- + buf[IP_VERSION] = 0x45; + buf[IP_TOS] = 0; + buf[IP_LEN+0] = (BOOTP_END) >> 8; + buf[IP_LEN+1] = (BOOTP_END) & 0xff; + buf[IP_ID+0] = 0; + buf[IP_ID+1] = 0; + buf[IP_FLAGS+0] = 0; + buf[IP_FLAGS+1] = 0; + buf[IP_TTL] = 63; + buf[IP_PROTOCOL] = 17; /* UDP */ + buf[IP_CHECKSUM+0] = 0; + buf[IP_CHECKSUM+1] = 0; + memset(buf+IP_SOURCE, 0, 4); + memset(buf+IP_DEST, 0xFF, 4); + + sum = ipv4_checksum((unsigned short*)(buf+IP_VERSION), (IP_END-IP_VERSION)/2); + buf[IP_CHECKSUM+0] = sum >> 8; + buf[IP_CHECKSUM+1] = sum & 0xff; + + mprintf("Sending BOOTP request...\n"); + return BOOTP_END; +} + +int process_bootp(uint8_t* buf, int len) +{ + uint8_t mac[6]; + get_mac_addr(mac); + + mprintf("recvd: %d %x %d %d %d\n", len, buf[IP_VERSION], buf[IP_PROTOCOL], buf[UDP_DPORT+1], buf[UDP_SPORT+1]); + if (len != BOOTP_END) return 0; + + if (buf[IP_VERSION] != 0x45) return 0; + + if (buf[IP_PROTOCOL] != 17 || + buf[UDP_DPORT] != 0 || buf[UDP_DPORT+1] != 68 || + buf[UDP_SPORT] != 0 || buf[UDP_SPORT+1] != 67) return 0; + + if (memcmp(buf+BOOTP_CHADDR, mac, 6)) return 0; + + mprintf("Discovered IP address!\n"); + memcpy(myIP, buf+BOOTP_YIADDR, 4); + return 1; +} diff --git a/lib/icmp.c b/lib/icmp.c index d2654703308b09b89de9dd862afe23489b284aee..9091ebd9fe2873a6946ee7b76018db14fe2797cb 100644 --- a/lib/icmp.c +++ b/lib/icmp.c @@ -3,8 +3,6 @@ #include "ipv4.h" #include "ptpd_netif.h" -static wr_socket_t* icmp_socket; - #define IP_VERSION 0 #define IP_TOS (IP_VERSION+1) #define IP_LEN (IP_TOS+1) @@ -22,20 +20,7 @@ static wr_socket_t* icmp_socket; #define ICMP_CHECKSUM (ICMP_CODE+1) #define ICMP_END (ICMP_CHECKSUM+2) -void icmp_init(const char* if_name) { - wr_sockaddr_t saddr; - - /* Configure socket filter */ - memset(&saddr, 0, sizeof(saddr)); - strcpy(saddr.if_name, if_name); - get_mac_addr(&saddr.mac); /* Unicast */ - saddr.ethertype = htons(0x0800); /* IPv4 */ - saddr.family = PTPD_SOCK_RAW_ETHERNET; - - icmp_socket = ptpd_netif_create_socket(PTPD_SOCK_RAW_ETHERNET, 0, &saddr); -} - -static int process_icmp(uint8_t* buf, int len) { +int process_icmp(uint8_t* buf, int len) { int iplen, hisBodyLen; uint8_t hisIP[4]; uint16_t sum; @@ -89,13 +74,3 @@ static int process_icmp(uint8_t* buf, int len) { return 24+hisBodyLen; } - -void icmp_poll(void) { - uint8_t buf[ICMP_END+136]; - wr_sockaddr_t addr; - int len; - - if ((len = ptpd_netif_recvfrom(icmp_socket, &addr, buf, sizeof(buf), 0)) > 0) - if ((len = process_icmp(buf, len)) > 0) - ptpd_netif_sendto(icmp_socket, &addr, buf, len, 0); -} diff --git a/lib/ipv4.c b/lib/ipv4.c index 36818665462e91020160996b96fb3d2baffaa72b..3565853f6cf0f22b7c5a6b4cfb22a722299e5d3c 100644 --- a/lib/ipv4.c +++ b/lib/ipv4.c @@ -2,8 +2,11 @@ #include "endpoint.h" #include "ipv4.h" +#include "ptpd_netif.h" uint8_t myIP[4]; +int needIP = 1; +static wr_socket_t* ipv4_socket; unsigned int ipv4_checksum(unsigned short* buf, int shorts) { int i; @@ -19,19 +22,45 @@ unsigned int ipv4_checksum(unsigned short* buf, int shorts) { return (~sum & 0xffff); } -void ipv4_init(const char* if_name, uint32_t ip) { - uint32_t ip_bigendian; +void ipv4_init(const char* if_name) { + wr_sockaddr_t saddr; - ip_bigendian = htonl(ip); - memcpy(myIP, &ip_bigendian, 4); + /* Configure socket filter */ + memset(&saddr, 0, sizeof(saddr)); + strcpy(saddr.if_name, if_name); + get_mac_addr(&saddr.mac[0]); /* Unicast */ + saddr.ethertype = htons(0x0800); /* IPv4 */ + saddr.family = PTPD_SOCK_RAW_ETHERNET; - arp_init(if_name); - icmp_init(if_name); - - // TRACE_DEV("My IP: %d.%d.%d.%d\n", myIP[0], myIP[1], myIP[2], myIP[3]); + ipv4_socket = ptpd_netif_create_socket(PTPD_SOCK_RAW_ETHERNET, 0, &saddr); } void ipv4_poll(void) { - arp_poll(); - icmp_poll(); + static int retry = 0; + static int timer = 0; + + uint8_t buf[400]; + wr_sockaddr_t addr; + int len; + + if ((len = ptpd_netif_recvfrom(ipv4_socket, &addr, buf, sizeof(buf), 0)) > 0) { + if (needIP && process_bootp(buf, len-14)) { + retry = 0; + needIP = 0; + timer = 0; + } + + if (!needIP && (len = process_icmp(buf, len-14)) > 0) + ptpd_netif_sendto(ipv4_socket, &addr, buf, len, 0); + } + + if (needIP && timer == 0) { + len = send_bootp(buf, ++retry); + + memset(addr.mac, 0xFF, 6); + addr.ethertype = htons(0x0800); /* IPv4 */ + ptpd_netif_sendto(ipv4_socket, &addr, buf, len, 0); + } + + if (needIP && ++timer == 100000) timer = 0; } diff --git a/lib/ipv4.h b/lib/ipv4.h index 8b7c92ab025a273afaf36124c3f8d04510c1a296..0c2e621ad6da571f1812e8f5974d10fbe47658a5 100644 --- a/lib/ipv4.h +++ b/lib/ipv4.h @@ -1,17 +1,21 @@ #ifndef IPV4_H #define IPV4_H -void ipv4_init(const char* if_name, uint32_t ip); +void ipv4_init(const char* if_name); void ipv4_poll(void); /* Internal to IP stack: */ unsigned int ipv4_checksum(unsigned short* buf, int shorts); + void arp_init(const char* if_name); -void icmp_init(const char* if_name); void arp_poll(void); -void icmp_poll(void); extern uint8_t myMAC[6]; extern uint8_t myIP[4]; +extern int needIP; + +int process_icmp(uint8_t* buf, int len); +int process_bootp(uint8_t* buf, int len); /* non-zero if IP was set */ +int send_bootp(uint8_t* buf, int retry); #endif diff --git a/lib/lib.mk b/lib/lib.mk index 53b47b39aa1e72cfed552a7fa96963a8ad20d705..eca0978b84b3321b95a538dfb43e1cb2c73d8250 100644 --- a/lib/lib.mk +++ b/lib/lib.mk @@ -3,6 +3,6 @@ OBJS_LIB= lib/mprintf.o \ ifneq ($(WITH_ETHERBONE), 0) -OBJS_LIB += lib/arp.o lib/icmp.o lib/ipv4.o +OBJS_LIB += lib/arp.o lib/icmp.o lib/ipv4.o lib/bootp.o endif \ No newline at end of file diff --git a/shell/cmd_ip.c b/shell/cmd_ip.c index 3d2f86ace6492732fbe7c48fe36a6c8ef1730f3b..f577fad41bbfcea8728f4e328acf314ae835910e 100644 --- a/shell/cmd_ip.c +++ b/shell/cmd_ip.c @@ -27,10 +27,15 @@ int cmd_ip(const char *args[]) } else if (!strcasecmp(args[0], "set") && args[1]) { decode_ip(args[1], ip); memcpy(myIP, ip, 4); + needIP = !ip[0] && !ip[1] && !ip[2] && !ip[3]; } else { return -EINVAL; } - mprintf("IP-address: %d.%d.%d.%d\n", - ip[0], ip[1], ip[2], ip[3]); + if (needIP) { + mprintf("IP-address: in training\n"); + } else { + mprintf("IP-address: %d.%d.%d.%d\n", + ip[0], ip[1], ip[2], ip[3]); + } } diff --git a/shell/cmd_mac.c b/shell/cmd_mac.c index c87cf1054273246c9e493eea67bf2ff79d8dc408..e5c8bd63c901dc5c75b5004a58ad1bc141ebea9a 100644 --- a/shell/cmd_mac.c +++ b/shell/cmd_mac.c @@ -31,6 +31,7 @@ int cmd_mac(const char *args[]) } else if (!strcasecmp(args[0], "set") && args[1]) { decode_mac(args[1], mac); set_mac_addr(mac); + pfilter_init_default(); } else if (!strcasecmp(args[0], "setp") && args[1]) { decode_mac(args[1], mac); set_persistent_mac(mac); diff --git a/wrc_main.c b/wrc_main.c index 3662bcacb5342875c3d57e75a81457f6fd132df2..9b322d4bd923a771ca40e073a7994b91fdc6ccc4 100644 --- a/wrc_main.c +++ b/wrc_main.c @@ -14,6 +14,7 @@ //#include "eeprom.h" #include "softpll_ng.h" #include "persistent_mac.h" +#include "lib/ipv4.h" #include "wrc_ptp.h" @@ -59,9 +60,8 @@ void wrc_initialize() pps_gen_init(); wrc_ptp_init(); - /* Derive the IP from the MAC address (10.x.y.z) */ - /* This will be done with BOOTP in the near future */ - ipv4_init("wru1", 0x0A000000 | mac_addr[3] << 16 | mac_addr[4] << 8 | mac_addr[5]); + ipv4_init("wru1"); + arp_init("wru1"); } #define LINK_WENT_UP 1 @@ -136,33 +136,34 @@ int main(void) wrc_gui_mode = 0; wrc_initialize(); - - shell_init(); - - wrc_ptp_set_mode(WRC_MODE_SLAVE); - wrc_ptp_start(); - - for(;;) - { - + shell_init(); + + wrc_ptp_set_mode(WRC_MODE_SLAVE); + wrc_ptp_start(); + + for (;;) + { int l_status = wrc_check_link(); switch (l_status) { + case LINK_WENT_UP: + needIP = 1; + break; + case LINK_UP: update_rx_queues(); + ipv4_poll(); + arp_poll(); break; case LINK_WENT_DOWN: spll_init(SPLL_MODE_FREE_RUNNING_MASTER, 0, 1); - break; - } + } - ui_update(); - wrc_ptp_update(); + ui_update(); + wrc_ptp_update(); spll_update_aux_clocks(); - ipv4_poll(); } } -