Commit 0c72e452 authored by Alessandro Rubini's avatar Alessandro Rubini

Merge branch 'network cleanup'

parents 7bab5d84 03285ba4
...@@ -83,6 +83,14 @@ config CMD_CONFIG ...@@ -83,6 +83,14 @@ config CMD_CONFIG
reports the current configuration. This adds half a kilobyte reports the current configuration. This adds half a kilobyte
to the binary size (100b for the code plus the .config file). to the binary size (100b for the code plus the .config file).
config SYSLOG
depends on IP
boolean "Include syslog client support"
help
This enable a UDP syslog client, configured by a shell command.
The user (or init script) must use "syslog <ipaddr> <macaddr>"
to enable it. The special "off" ipaddr disables syslog.
# #
# This is a set of configuration options that should not be changed by # This is a set of configuration options that should not be changed by
# normal users. If the "developer" menu is used, the binary is tainted. # normal users. If the "developer" menu is used, the binary is tainted.
......
...@@ -13,8 +13,9 @@ CONFIG_STACKSIZE=2048 ...@@ -13,8 +13,9 @@ CONFIG_STACKSIZE=2048
CONFIG_PPSI=y CONFIG_PPSI=y
CONFIG_UART=y CONFIG_UART=y
CONFIG_W1=y CONFIG_W1=y
# CONFIG_IP is not set CONFIG_IP=y
# CONFIG_CMD_CONFIG is not set CONFIG_CMD_CONFIG=y
CONFIG_SYSLOG=y
# #
# wrpc-sw is tainted if you change the following options # wrpc-sw is tainted if you change the following options
......
...@@ -194,7 +194,7 @@ int minic_poll_rx() ...@@ -194,7 +194,7 @@ int minic_poll_rx()
int minic_rx_frame(uint8_t * hdr, uint8_t * payload, uint32_t buf_size, int minic_rx_frame(uint8_t * hdr, uint8_t * payload, uint32_t buf_size,
struct hw_timestamp *hwts) struct hw_timestamp *hwts)
{ {
uint32_t payload_size, num_words; uint32_t frame_size, payload_size, num_words;
uint32_t desc_hdr; uint32_t desc_hdr;
uint32_t raw_ts; uint32_t raw_ts;
uint32_t cur_avail; uint32_t cur_avail;
...@@ -217,8 +217,8 @@ int minic_rx_frame(uint8_t * hdr, uint8_t * payload, uint32_t buf_size, ...@@ -217,8 +217,8 @@ int minic_rx_frame(uint8_t * hdr, uint8_t * payload, uint32_t buf_size,
} }
return 0; return 0;
} }
payload_size = RX_DESC_SIZE(desc_hdr); frame_size = RX_DESC_SIZE(desc_hdr);
num_words = ((payload_size + 3) >> 2) + 1; num_words = ((frame_size + 3) >> 2) + 1;
/* valid packet */ /* valid packet */
if (!RX_DESC_ERROR(desc_hdr)) { if (!RX_DESC_ERROR(desc_hdr)) {
...@@ -229,15 +229,15 @@ int minic_rx_frame(uint8_t * hdr, uint8_t * payload, uint32_t buf_size, ...@@ -229,15 +229,15 @@ int minic_rx_frame(uint8_t * hdr, uint8_t * payload, uint32_t buf_size,
int cntr_diff; int cntr_diff;
uint16_t dhdr; uint16_t dhdr;
payload_size -= RX_OOB_SIZE; frame_size -= RX_OOB_SIZE;
/* fixme: ugly way of doing unaligned read */ /* fixme: ugly way of doing unaligned read */
minic_rx_memcpy((uint8_t *) & raw_ts, minic_rx_memcpy((uint8_t *) & raw_ts,
(uint8_t *) minic.rx_head (uint8_t *) minic.rx_head
+ payload_size + 6, 4); + frame_size + 6, 4);
minic_rx_memcpy((uint8_t *) & dhdr, minic_rx_memcpy((uint8_t *) & dhdr,
(uint8_t *) minic.rx_head + (uint8_t *) minic.rx_head +
payload_size + 4, 2); frame_size + 4, 2);
EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f); EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f);
shw_pps_gen_get_time(&sec, &counter_ppsg); shw_pps_gen_get_time(&sec, &counter_ppsg);
...@@ -258,14 +258,14 @@ int minic_rx_frame(uint8_t * hdr, uint8_t * payload, uint32_t buf_size, ...@@ -258,14 +258,14 @@ int minic_rx_frame(uint8_t * hdr, uint8_t * payload, uint32_t buf_size,
hwts->nsec = counter_r * (REF_CLOCK_PERIOD_PS / 1000); hwts->nsec = counter_r * (REF_CLOCK_PERIOD_PS / 1000);
hwts->valid = (dhdr & RXOOB_TS_INCORRECT) ? 0 : 1; hwts->valid = (dhdr & RXOOB_TS_INCORRECT) ? 0 : 1;
} }
payload_size = frame_size - ETH_HEADER_SIZE;
n_recvd = (buf_size < payload_size ? buf_size : payload_size); n_recvd = (buf_size < payload_size ? buf_size : payload_size);
minic.rx_count++; minic.rx_count++;
minic_rx_memcpy(hdr, (void *)minic.rx_head + 4, minic_rx_memcpy(hdr, (void *)minic.rx_head + 4,
ETH_HEADER_SIZE); ETH_HEADER_SIZE);
minic_rx_memcpy(payload, (void *)minic.rx_head + 4 minic_rx_memcpy(payload, (void *)minic.rx_head + 4
+ ETH_HEADER_SIZE, n_recvd - ETH_HEADER_SIZE); + ETH_HEADER_SIZE, n_recvd);
} else { } else {
n_recvd = -1; n_recvd = -1;
} }
...@@ -299,9 +299,9 @@ int minic_tx_frame(uint8_t * hdr, uint8_t * payload, uint32_t size, ...@@ -299,9 +299,9 @@ int minic_tx_frame(uint8_t * hdr, uint8_t * payload, uint32_t size,
memset((void *)minic.tx_head, 0x0, size + 16); memset((void *)minic.tx_head, 0x0, size + 16);
memset((void *)minic.tx_head + 4, 0, size < 60 ? 60 : size); memset((void *)minic.tx_head + 4, 0, size < 60 ? 60 : size);
memcpy((void *)minic.tx_head + 4, hdr, ETH_HEADER_SIZE); memcpy((void *)minic.tx_head + 4, hdr, ETH_HEADER_SIZE);
memcpy((void *)minic.tx_head + 4 + ETH_HEADER_SIZE, payload, memcpy((void *)minic.tx_head + 4 + ETH_HEADER_SIZE, payload, size);
size - ETH_HEADER_SIZE);
size += ETH_HEADER_SIZE;
if (size < 60) if (size < 60)
size = 60; size = 60;
......
...@@ -31,10 +31,10 @@ ...@@ -31,10 +31,10 @@
#define UART_BAUDRATE 115200ULL #define UART_BAUDRATE 115200ULL
/* Maximum number of simultaneously created sockets */ /* Maximum number of simultaneously created sockets */
#define NET_MAX_SOCKETS 4 #define NET_MAX_SOCKETS 8
/* Socket buffer size, determines the max. RX packet size */ /* Socket buffer size, determines the max. RX packet size */
#define NET_SKBUF_SIZE 512 #define NET_MAX_SKBUF_SIZE 512
/* Number of auxillary clock channels - usually equal to the number of FMCs */ /* Number of auxillary clock channels - usually equal to the number of FMCs */
#define NUM_AUX_CLOCKS 1 #define NUM_AUX_CLOCKS 1
......
...@@ -15,17 +15,13 @@ ...@@ -15,17 +15,13 @@
#include <board.h> #include <board.h>
//#include <inttypes.h> //#include <inttypes.h>
#define PTPD_SOCK_RAW_ETHERNET 1 /* used in ppsi to no aim: remove this */ #define PTPD_SOCK_UDP 0 /* wrong name, it should be "WRPC" */
#define PTPD_SOCK_RAW_ETHERNET 1 /* but used in ppsi, which I won't change */
#define PTPD_FLAGS_MULTICAST 0x1 #define LINK_WENT_UP 1
#define LINK_WENT_DOWN 2
// error codes (to be extended) #define LINK_UP 3
#define PTPD_NETIF_READY 1 #define LINK_DOWN 4
#define PTPD_NETIF_OK 0
#define PTPD_NETIF_ERROR -1
#define PTPD_NETIF_NOT_READY -2
#define PTPD_NETIF_NOT_FOUND -3
// GCC-specific // GCC-specific
#ifndef PACKED #ifndef PACKED
...@@ -34,35 +30,36 @@ ...@@ -34,35 +30,36 @@
#define PHYS_PORT_ANY (0xffff) #define PHYS_PORT_ANY (0xffff)
#define PTPD_NETIF_TX 1
#define PTPD_NETIF_RX 2
#define IFACE_NAME_LEN 16
#define SLAVE_PRIORITY_0 0
#define SLAVE_PRIORITY_1 1
#define SLAVE_PRIORITY_2 2
#define SLAVE_PRIORITY_3 3
#define SLAVE_PRIORITY_4 4
// Some system-independent definitions // Some system-independent definitions
typedef uint8_t mac_addr_t[6]; typedef uint8_t mac_addr_t[6];
typedef uint32_t ipv4_addr_t;
// WhiteRabbit socket - it's void pointer as the real socket structure is private and probably platform-specific.
typedef void *wr_socket_t;
// Socket address for ptp_netif_ functions // Socket address for ptp_netif_ functions
typedef struct { struct wr_sockaddr {
// MAC address // MAC address
mac_addr_t mac; mac_addr_t mac;
// Destination MASC address, filled by recvfrom() function on interfaces bound to multiple addresses // Destination MAC address, filled by recvfrom()
mac_addr_t mac_dest; mac_addr_t mac_dest;
// RAW ethertype // RAW ethertype
uint16_t ethertype; uint16_t ethertype;
} wr_sockaddr_t; uint16_t udpport;
};
struct sockq {
uint16_t head, tail, avail, size;
uint16_t n;
uint8_t *buff;
};
PACKED struct _wr_timestamp { struct wrpc_socket {
struct wr_sockaddr bind_addr;
mac_addr_t local_mac;
uint32_t phase_transition;
uint32_t dmtd_phase;
struct sockq queue;
};
PACKED struct wr_timestamp {
// Seconds // Seconds
int64_t sec; int64_t sec;
...@@ -70,7 +67,7 @@ PACKED struct _wr_timestamp { ...@@ -70,7 +67,7 @@ PACKED struct _wr_timestamp {
// Nanoseconds // Nanoseconds
int32_t nsec; int32_t nsec;
// Phase (in picoseconds), linearized for receive timestamps, zero for send timestamps // Phase (in picoseconds), linearized for rx, zero for send timestamps
int32_t phase; // phase(picoseconds) int32_t phase; // phase(picoseconds)
/* Raw time (non-linearized) for debugging purposes */ /* Raw time (non-linearized) for debugging purposes */
...@@ -78,54 +75,48 @@ PACKED struct _wr_timestamp { ...@@ -78,54 +75,48 @@ PACKED struct _wr_timestamp {
int32_t raw_nsec; int32_t raw_nsec;
int32_t raw_ahead; int32_t raw_ahead;
// correctness flag: when 0, the timestamp MAY be incorrect (e.g. generated during timebase adjustment) // when 0, tstamp MAY be incorrect (e.g. during timebase adjustment)
int correct; int correct;
//int cntr_ahead;
}; };
typedef struct _wr_timestamp wr_timestamp_t;
/* OK. These functions we'll develop along with network card driver. You can write your own UDP-based stubs for testing purposes. */
// Initialization of network interface:
// - opens devices
// - does necessary ioctls()
// - initializes connection with the mighty HAL daemon
int ptpd_netif_init(void);
// Creates UDP or Ethernet RAW socket (determined by sock_type) bound to bind_addr. If PTPD_FLAG_MULTICAST is set, the socket is // Creates UDP or Ethernet RAW socket (determined by sock_type) bound
// automatically added to multicast group. User can specify physical_port field to bind the socket to specific switch port only. // to bind_addr. If PTPD_FLAG_MULTICAST is set, the socket is
wr_socket_t *ptpd_netif_create_socket(int unused, int unused2, // automatically added to multicast group. User can specify
wr_sockaddr_t * bind_addr); // physical_port field to bind the socket to specific switch port only.
struct wrpc_socket *ptpd_netif_create_socket(struct wrpc_socket *s,
struct wr_sockaddr * bind_addr,
int udp_or_raw, int udpport);
// Sends a UDP/RAW packet (data, data_length) to address provided in wr_sockaddr_t. // Sends a UDP/RAW packet (data, data_length) to addr in wr_sockaddr.
// For raw frames, mac/ethertype needs to be provided, for UDP - ip/port. // For raw frames, mac/ethertype needs to be provided, for UDP - ip/port.
// Every transmitted frame has assigned a tag value, stored at tag parameter. This value is later used // Every transmitted frame has assigned a tag value, stored at tag parameter.
// for recovering the precise transmit timestamp. If user doesn't need it, tag parameter can be left NULL. // This value is later used for recovering the precise transmit timestamp.
// If user doesn't need it, tag parameter can be left NULL.
int ptpd_netif_sendto(wr_socket_t * sock, wr_sockaddr_t * to, void *data, int ptpd_netif_sendto(struct wrpc_socket *sock, struct wr_sockaddr *to, void *data,
size_t data_length, wr_timestamp_t * tx_ts); size_t data_length, struct wr_timestamp *tx_ts);
// Receives an UDP/RAW packet. Data is written to (data) and length is returned. Maximum buffer length can be specified // Receives an UDP/RAW packet. Data is written to (data) and len is returned.
// by data_length parameter. Sender information is stored in structure specified in 'from'. All RXed packets are timestamped and the timestamp // Maximum buffer length can be specified by data_length parameter.
// Sender information is stored in structure specified in 'from'.
// All RXed packets are timestamped and the timestamp
// is stored in rx_timestamp (unless it's NULL). // is stored in rx_timestamp (unless it's NULL).
int ptpd_netif_recvfrom(wr_socket_t * sock, wr_sockaddr_t * from, void *data, int ptpd_netif_recvfrom(struct wrpc_socket *sock, struct wr_sockaddr *from, void *data,
size_t data_length, wr_timestamp_t * rx_timestamp); size_t data_length, struct wr_timestamp *rx_timestamp);
// Closes the socket. // Closes the socket.
int ptpd_netif_close_socket(wr_socket_t * sock); int ptpd_netif_close_socket(struct wrpc_socket * sock);
int ptpd_netif_get_hw_addr(wr_socket_t * sock, mac_addr_t * mac);
int ptpd_netif_get_hw_addr(wr_socket_t * sock, mac_addr_t * mac); int ptpd_netif_get_hw_addr(struct wrpc_socket * sock, mac_addr_t * mac);
void ptpd_netif_linearize_rx_timestamp(wr_timestamp_t * ts, int32_t dmtd_phase, void ptpd_netif_linearize_rx_timestamp(struct wr_timestamp *ts,
int32_t dmtd_phase,
int cntr_ahead, int transition_point, int cntr_ahead, int transition_point,
int clock_period); int clock_period);
void ptpd_netif_set_phase_transition(uint32_t phase); void ptpd_netif_set_phase_transition(uint32_t phase);
struct hal_port_state; struct hal_port_state;
int wrpc_get_port_state(struct hal_port_state *port, const char *port_name /* unused */); int wrpc_get_port_state(struct hal_port_state *port,
const char *port_name /* unused */);
#endif /* __PTPD_NETIF_H */ #endif /* __PTPD_NETIF_H */
...@@ -14,6 +14,10 @@ extern int wrc_stat_running; ...@@ -14,6 +14,10 @@ extern int wrc_stat_running;
const char *fromhex(const char *hex, int *v); const char *fromhex(const char *hex, int *v);
const char *fromdec(const char *dec, int *v); const char *fromdec(const char *dec, int *v);
void decode_mac(const char *str, unsigned char *mac);
char *format_mac(char *s, const unsigned char *mac);
void decode_ip(const char *str, unsigned char *ip);
char *format_ip(char *s, const unsigned char *ip);
struct wrc_shell_cmd { struct wrc_shell_cmd {
char *name; char *name;
......
...@@ -16,7 +16,10 @@ ...@@ -16,7 +16,10 @@
#define C_BLUE 4 #define C_BLUE 4
/* Return TAI date/time in human-readable form. Non-reentrant. */ /* Return TAI date/time in human-readable form. Non-reentrant. */
char *format_time(uint64_t sec); char *format_time(uint64_t sec, int format);
#define TIME_FORMAT_LEGACY 0
#define TIME_FORMAT_SYSLOG 1
#define TIME_FORMAT_SORTED 2
/* Color printf() variant. */ /* Color printf() variant. */
void cprintf(int color, const char *fmt, ...); void cprintf(int color, const char *fmt, ...);
......
...@@ -16,7 +16,12 @@ ...@@ -16,7 +16,12 @@
#define htons(x) x #define htons(x) x
#endif #endif
static wr_socket_t *arp_socket; static uint8_t __arp_queue[128];
static struct wrpc_socket __static_arp_socket = {
.queue.buff = __arp_queue,
.queue.size = sizeof(__arp_queue),
};
static struct wrpc_socket *arp_socket;
#define ARP_HTYPE 0 #define ARP_HTYPE 0
#define ARP_PTYPE (ARP_HTYPE+2) #define ARP_PTYPE (ARP_HTYPE+2)
...@@ -31,14 +36,15 @@ static wr_socket_t *arp_socket; ...@@ -31,14 +36,15 @@ static wr_socket_t *arp_socket;
void arp_init(void) void arp_init(void)
{ {
wr_sockaddr_t saddr; struct wr_sockaddr saddr;
/* Configure socket filter */ /* Configure socket filter */
memset(&saddr, 0, sizeof(saddr)); memset(&saddr, 0, sizeof(saddr));
memset(&saddr.mac, 0xFF, 6); /* Broadcast */ memset(&saddr.mac, 0xFF, 6); /* Broadcast */
saddr.ethertype = htons(0x0806); /* ARP */ saddr.ethertype = htons(0x0806); /* ARP */
arp_socket = ptpd_netif_create_socket(0, 0 /* both unused */, &saddr); arp_socket = ptpd_netif_create_socket(&__static_arp_socket, &saddr,
PTPD_SOCK_RAW_ETHERNET, 0);
} }
static int process_arp(uint8_t * buf, int len) static int process_arp(uint8_t * buf, int len)
...@@ -85,7 +91,7 @@ static int process_arp(uint8_t * buf, int len) ...@@ -85,7 +91,7 @@ static int process_arp(uint8_t * buf, int len)
void arp_poll(void) void arp_poll(void)
{ {
uint8_t buf[ARP_END + 100]; uint8_t buf[ARP_END + 100];
wr_sockaddr_t addr; struct wr_sockaddr addr;
int len; int len;
if (needIP) if (needIP)
......
...@@ -12,30 +12,6 @@ ...@@ -12,30 +12,6 @@
#include "ipv4.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_OP (UDP_END)
#define BOOTP_HTYPE (BOOTP_OP+1) #define BOOTP_HTYPE (BOOTP_OP+1)
#define BOOTP_HLEN (BOOTP_HTYPE+1) #define BOOTP_HLEN (BOOTP_HTYPE+1)
...@@ -53,9 +29,9 @@ ...@@ -53,9 +29,9 @@
#define BOOTP_VEND (BOOTP_FILE+128) #define BOOTP_VEND (BOOTP_FILE+128)
#define BOOTP_END (BOOTP_VEND+64) #define BOOTP_END (BOOTP_VEND+64)
int send_bootp(uint8_t * buf, int retry) int prepare_bootp(struct wr_sockaddr *addr, uint8_t * buf, int retry)
{ {
unsigned short sum; struct wr_udp_addr uaddr;
// ----------- BOOTP ------------ // ----------- BOOTP ------------
buf[BOOTP_OP] = 1; /* bootrequest */ buf[BOOTP_OP] = 1; /* bootrequest */
...@@ -86,54 +62,16 @@ int send_bootp(uint8_t * buf, int retry) ...@@ -86,54 +62,16 @@ int send_bootp(uint8_t * buf, int retry)
memset(buf + BOOTP_FILE, 0, 128); /* desired BOOTP file */ memset(buf + BOOTP_FILE, 0, 128); /* desired BOOTP file */
memset(buf + BOOTP_VEND, 0, 64); /* vendor extensions */ memset(buf + BOOTP_VEND, 0, 64); /* vendor extensions */
// ------------ UDP ------------- /* complete with udp helper */
memset(buf + UDP_VIRT_SADDR, 0, 4); memset(&uaddr.saddr, 0, 4);
memset(buf + UDP_VIRT_DADDR, 0xFF, 4); memset(&uaddr.daddr, 0xff, 4);
buf[UDP_VIRT_ZEROS] = 0; uaddr.sport = ntohs(68);
buf[UDP_VIRT_PROTO] = 0x11; /* UDP */ uaddr.dport = ntohs(67);
buf[UDP_VIRT_LENGTH] = (BOOTP_END - IP_END) >> 8;
buf[UDP_VIRT_LENGTH + 1] = (BOOTP_END - IP_END) & 0xff; fill_udp(buf, BOOTP_END, &uaddr);
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;
/* and fix destination before sending it */
memset(addr->mac, 0xFF, 6);
// pp_printf("Sending BOOTP request...\n"); // pp_printf("Sending BOOTP request...\n");
return BOOTP_END; return BOOTP_END;
} }
...@@ -148,12 +86,7 @@ int process_bootp(uint8_t * buf, int len) ...@@ -148,12 +86,7 @@ int process_bootp(uint8_t * buf, int len)
if (len != BOOTP_END) if (len != BOOTP_END)
return 0; return 0;
if (buf[IP_VERSION] != 0x45) if (buf[UDP_SPORT] != 0 || buf[UDP_SPORT + 1] != 67)
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; return 0;
if (memcmp(buf + BOOTP_CHADDR, mac, 6)) if (memcmp(buf + BOOTP_CHADDR, mac, 6))
......
...@@ -7,10 +7,12 @@ ...@@ -7,10 +7,12 @@
* Released according to the GNU GPL, version 2 or any later version. * Released according to the GNU GPL, version 2 or any later version.
*/ */
#include <string.h> #include <string.h>
#include <wrpc.h>
#include "endpoint.h" #include "endpoint.h"
#include "ipv4.h" #include "ipv4.h"
#include "ptpd_netif.h" #include "ptpd_netif.h"
#include "pps_gen.h"
#include "hw/memlayout.h" #include "hw/memlayout.h"
#include "hw/etherbone-config.h" #include "hw/etherbone-config.h"
...@@ -20,7 +22,37 @@ ...@@ -20,7 +22,37 @@
int needIP = 1; int needIP = 1;
static uint8_t myIP[4]; static uint8_t myIP[4];
static wr_socket_t *ipv4_socket;
/* bootp: bigger buffer, UDP based */
static uint8_t __bootp_queue[512];
static struct wrpc_socket __static_bootp_socket = {
.queue.buff = __bootp_queue,
.queue.size = sizeof(__bootp_queue),
};
static struct wrpc_socket *bootp_socket;
/* ICMP: smaller buffer */
static uint8_t __icmp_queue[128];
static struct wrpc_socket __static_icmp_socket = {
.queue.buff = __icmp_queue,
.queue.size = sizeof(__icmp_queue),
};
static struct wrpc_socket *icmp_socket;
/* RDATE: even smaller buffer -- but we require 86. 96 is "even". */
static uint8_t __rdate_queue[96];
static struct wrpc_socket __static_rdate_socket = {
.queue.buff = __rdate_queue,
.queue.size = sizeof(__rdate_queue),
};
static struct wrpc_socket *rdate_socket;
/* syslog is selected by Kconfig, so we have weak aliases here */
void __attribute__((weak)) syslog_init(void)
{ }
void __attribute__((weak)) syslog_poll(int l_status)
{ }
unsigned int ipv4_checksum(unsigned short *buf, int shorts) unsigned int ipv4_checksum(unsigned short *buf, int shorts)
{ {
...@@ -29,7 +61,7 @@ unsigned int ipv4_checksum(unsigned short *buf, int shorts) ...@@ -29,7 +61,7 @@ unsigned int ipv4_checksum(unsigned short *buf, int shorts)
sum = 0; sum = 0;
for (i = 0; i < shorts; ++i) for (i = 0; i < shorts; ++i)
sum += buf[i]; sum += ntohs(buf[i]);
sum = (sum >> 16) + (sum & 0xffff); sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16); sum += (sum >> 16);
...@@ -39,47 +71,106 @@ unsigned int ipv4_checksum(unsigned short *buf, int shorts) ...@@ -39,47 +71,106 @@ unsigned int ipv4_checksum(unsigned short *buf, int shorts)
void ipv4_init(void) void ipv4_init(void)
{ {
wr_sockaddr_t saddr; struct wr_sockaddr saddr;
/* Bootp: use UDP engine activated but function arguments */
bootp_socket = ptpd_netif_create_socket(&__static_bootp_socket, NULL,
PTPD_SOCK_UDP, 68 /* bootpc */);
/* Reset => need a fresh IP */ /* time (rdate): UDP */
needIP = 1; rdate_socket = ptpd_netif_create_socket(&__static_rdate_socket, NULL,
PTPD_SOCK_UDP, 37 /* time */);
/* Configure socket filter */ /* ICMP: specify raw (not UDP), with IPV4 ethtype */
memset(&saddr, 0, sizeof(saddr)); memset(&saddr, 0, sizeof(saddr));
get_mac_addr(&saddr.mac[0]); /* Unicast */ saddr.ethertype = htons(0x0800);
saddr.ethertype = htons(0x0800); /* IPv4 */ icmp_socket = ptpd_netif_create_socket(&__static_icmp_socket, &saddr,
PTPD_SOCK_RAW_ETHERNET, 0);
ipv4_socket = ptpd_netif_create_socket(0, 0 /* both unused */, &saddr); syslog_init();
} }
static int bootp_retry = 0; static int bootp_retry = 0;
static int bootp_timer = 0; static uint32_t bootp_tics;
void ipv4_poll(void) /* receive bootp through the UDP mechanism */
static void bootp_poll(void)
{ {
struct wr_sockaddr addr;
uint8_t buf[400]; uint8_t buf[400];
wr_sockaddr_t addr;
int len; int len;
if ((len = ptpd_netif_recvfrom(ipv4_socket, &addr, if (!bootp_tics) /* first time ever */
buf, sizeof(buf), 0)) > 0) { bootp_tics = timer_get_tics() - 1;
if (needIP)
process_bootp(buf, len); len = ptpd_netif_recvfrom(bootp_socket, &addr,
buf, sizeof(buf), NULL);
if (len > 0 && needIP)
process_bootp(buf, len);
if (!needIP)
return;
if (time_before(timer_get_tics(), bootp_tics))
return;
len = prepare_bootp(&addr, buf, ++bootp_retry);
ptpd_netif_sendto(bootp_socket, &addr, buf, len, 0);
bootp_tics = timer_get_tics() + TICS_PER_SECOND;
}
static void icmp_poll(void)
{
struct wr_sockaddr addr;
uint8_t buf[128];
int len;
len = ptpd_netif_recvfrom(icmp_socket, &addr,
buf, sizeof(buf), NULL);
if (len <= 0)
return;
if (needIP)
return;
if ((len = process_icmp(buf, len)) > 0)
ptpd_netif_sendto(icmp_socket, &addr, buf, len, 0);
}
static void rdate_poll(void)
{
struct wr_sockaddr addr;
uint64_t secs;
uint32_t result;
uint8_t buf[32];
int len;
len = ptpd_netif_recvfrom(rdate_socket, &addr,
buf, sizeof(buf), NULL);
if (len <= 0)
return;
shw_pps_gen_get_time(&secs, NULL);
result = htonl((uint32_t)(secs + 2208988800LL));
/* Magic above: $(date +%s --date="Jan 1 1900 00:00:00 UTC)" */
if (!needIP && (len = process_icmp(buf, len)) > 0) len = UDP_END + sizeof(result);
ptpd_netif_sendto(ipv4_socket, &addr, buf, len, 0); memcpy(buf + UDP_END, &result, sizeof(result));
}
fill_udp(buf, len, NULL);
ptpd_netif_sendto(rdate_socket, &addr, buf, len, 0);
}
void ipv4_poll(int l_status)
{
if (l_status == LINK_WENT_UP)
needIP = 1;
bootp_poll();
if (needIP && bootp_timer == 0) { icmp_poll();
len = send_bootp(buf, ++bootp_retry);
memset(addr.mac, 0xFF, 6); rdate_poll();
addr.ethertype = htons(0x0800); /* IPv4 */
ptpd_netif_sendto(ipv4_socket, &addr, buf, len, 0);
}
if (needIP && ++bootp_timer == 100000) syslog_poll(l_status);
bootp_timer = 0;
} }
void getIP(unsigned char *IP) void getIP(unsigned char *IP)
...@@ -100,8 +191,6 @@ void setIP(unsigned char *IP) ...@@ -100,8 +191,6 @@ void setIP(unsigned char *IP)
*eb_ip = ip; *eb_ip = ip;
needIP = (ip == 0); needIP = (ip == 0);
if (!needIP) { if (!needIP)
bootp_retry = 0; bootp_retry = 0;
bootp_timer = 0;
}
} }
...@@ -7,9 +7,34 @@ ...@@ -7,9 +7,34 @@
#define IPV4_H #define IPV4_H
#include <inttypes.h> #include <inttypes.h>
#include "ptpd_netif.h" /* for sockaddr in prototype */
#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)
void ipv4_init(void); void ipv4_init(void);
void ipv4_poll(void); void ipv4_poll(int l_status);
/* Internal to IP stack: */ /* Internal to IP stack: */
unsigned int ipv4_checksum(unsigned short *buf, int shorts); unsigned int ipv4_checksum(unsigned short *buf, int shorts);
...@@ -23,6 +48,19 @@ void getIP(unsigned char *IP); ...@@ -23,6 +48,19 @@ void getIP(unsigned char *IP);
int process_icmp(uint8_t * buf, int len); int process_icmp(uint8_t * buf, int len);
int process_bootp(uint8_t * buf, int len); /* non-zero if IP was set */ int process_bootp(uint8_t * buf, int len); /* non-zero if IP was set */
int send_bootp(uint8_t * buf, int retry); int prepare_bootp(struct wr_sockaddr *addr, uint8_t * buf, int retry);
/* The UDP helper needs some information, if not replying to a frame */
struct wr_udp_addr {
uint32_t saddr; /* all fields in network order, for memcpy */
uint32_t daddr;
uint16_t sport;
uint16_t dport;
};
void fill_udp(uint8_t * buf, int len, struct wr_udp_addr *uaddr);
void syslog_init(void);
void syslog_poll(int l_status);
#endif #endif
obj-y += lib/util.o lib/atoi.o obj-y += lib/util.o lib/atoi.o
obj-y += lib/usleep.o obj-y += lib/usleep.o
obj-$(CONFIG_WR_NODE) += lib/net.o obj-$(CONFIG_WR_NODE) += lib/net.o lib/udp.o
obj-$(CONFIG_WR_NODE) += lib/arp.o lib/icmp.o lib/ipv4.o lib/bootp.o obj-$(CONFIG_WR_NODE) += lib/arp.o lib/icmp.o lib/ipv4.o lib/bootp.o
obj-$(CONFIG_SYSLOG) += lib/syslog.o
...@@ -22,47 +22,20 @@ ...@@ -22,47 +22,20 @@
#include "minic.h" #include "minic.h"
#include "endpoint.h" #include "endpoint.h"
#include "softpll_ng.h" #include "softpll_ng.h"
#include "ipv4.h"
#define min(x,y) ((x) < (y) ? (x) : (y)) #define min(x,y) ((x) < (y) ? (x) : (y))
__attribute__ ((packed))
struct ethhdr { struct ethhdr {
uint8_t dstmac[6]; uint8_t dstmac[6];
uint8_t srcmac[6]; uint8_t srcmac[6];
uint16_t ethtype; uint16_t ethtype;
}; };
struct timeout { static struct wrpc_socket *socks[NET_MAX_SOCKETS];
uint64_t start_tics;
uint64_t timeout;
};
struct sockq {
uint8_t buf[NET_SKBUF_SIZE];
uint16_t head, tail, avail;
uint16_t n;
};
struct my_socket {
int in_use;
wr_sockaddr_t bind_addr;
mac_addr_t local_mac;
uint32_t phase_transition;
uint32_t dmtd_phase;
struct sockq queue;
};
static struct my_socket socks[NET_MAX_SOCKETS];
int ptpd_netif_init()
{
memset(socks, 0, sizeof(socks));
return PTPD_NETIF_OK;
}
//#define net_verbose pp_printf //#define net_verbose pp_printf
int ptpd_netif_get_hw_addr(wr_socket_t * sock, mac_addr_t * mac) int ptpd_netif_get_hw_addr(struct wrpc_socket *sock, mac_addr_t *mac)
{ {
get_mac_addr((uint8_t *) mac); get_mac_addr((uint8_t *) mac);
...@@ -73,35 +46,45 @@ void ptpd_netif_set_phase_transition(uint32_t phase) ...@@ -73,35 +46,45 @@ void ptpd_netif_set_phase_transition(uint32_t phase)
{ {
int i; int i;
for (i=0; i< NET_MAX_SOCKETS; ++i) { for (i=0; i< ARRAY_SIZE(socks); ++i) {
socks[i].phase_transition = phase; socks[i]->phase_transition = phase;
} }
} }
wr_socket_t *ptpd_netif_create_socket(int unused, int unusd2, struct wrpc_socket *ptpd_netif_create_socket(struct wrpc_socket *sock,
wr_sockaddr_t * bind_addr) struct wr_sockaddr * bind_addr,
int udp_or_raw, int udpport)
{ {
int i; int i;
struct hal_port_state pstate; struct hal_port_state pstate;
struct my_socket *sock; static mac_addr_t zero_mac;
/* Look for the first available socket. */ /* Look for the first available socket. */
for (sock = NULL, i = 0; i < NET_MAX_SOCKETS; i++) for (i = 0; i < ARRAY_SIZE(socks); i++)
if (!socks[i].in_use) { if (!socks[i]) {
sock = &socks[i]; socks[i] = sock;
break; break;
} }
if (i == ARRAY_SIZE(socks)) {
if (!sock) { pp_printf("%s: no socket slots left\n", __func__);
net_verbose("No sockets left.\n");
return NULL; return NULL;
} }
if (wrpc_get_port_state(&pstate, "wr0" /* unused */) < 0) if (wrpc_get_port_state(&pstate, "wr0" /* unused */) < 0)
return NULL; return NULL;
memcpy(&sock->bind_addr, bind_addr, sizeof(wr_sockaddr_t)); /* copy and complete the bind information. If MAC is 0 use unicast */
memset(&sock->bind_addr, 0, sizeof(struct wr_sockaddr));
if (bind_addr)
memcpy(&sock->bind_addr, bind_addr, sizeof(struct wr_sockaddr));
if (!memcmp(sock->bind_addr.mac, zero_mac, ETH_ALEN))
get_mac_addr(sock->bind_addr.mac);
sock->bind_addr.udpport = 0;
if (udp_or_raw == PTPD_SOCK_UDP) {
sock->bind_addr.ethertype = htons(0x0800); /* IPv4 */
sock->bind_addr.udpport = udpport;
}
/*get mac from endpoint */ /*get mac from endpoint */
get_mac_addr(sock->local_mac); get_mac_addr(sock->local_mac);
...@@ -111,19 +94,18 @@ wr_socket_t *ptpd_netif_create_socket(int unused, int unusd2, ...@@ -111,19 +94,18 @@ wr_socket_t *ptpd_netif_create_socket(int unused, int unusd2,
/*packet queue */ /*packet queue */
sock->queue.head = sock->queue.tail = 0; sock->queue.head = sock->queue.tail = 0;
sock->queue.avail = NET_SKBUF_SIZE; sock->queue.avail = sock->queue.size;
sock->queue.n = 0; sock->queue.n = 0;
sock->in_use = 1;
return (wr_socket_t *) (sock); return sock;
} }
int ptpd_netif_close_socket(wr_socket_t * sock) int ptpd_netif_close_socket(struct wrpc_socket *s)
{ {
struct my_socket *s = (struct my_socket *)sock; int i;
for (i = 0; i < ARRAY_SIZE(socks); i++)
if (s) if (socks[i] == s)
s->in_use = 0; socks[i] = NULL;
return 0; return 0;
} }
...@@ -136,7 +118,8 @@ int ptpd_netif_close_socket(wr_socket_t * sock) ...@@ -136,7 +118,8 @@ int ptpd_netif_close_socket(wr_socket_t * sock)
* *
* Have a look at the note at http://ohwr.org/documents/xxx for details. * Have a look at the note at http://ohwr.org/documents/xxx for details.
*/ */
void ptpd_netif_linearize_rx_timestamp(wr_timestamp_t * ts, int32_t dmtd_phase, void ptpd_netif_linearize_rx_timestamp(struct wr_timestamp *ts,
int32_t dmtd_phase,
int cntr_ahead, int transition_point, int cntr_ahead, int transition_point,
int clock_period) int clock_period)
{ {
...@@ -202,20 +185,27 @@ void ptpd_netif_linearize_rx_timestamp(wr_timestamp_t * ts, int32_t dmtd_phase, ...@@ -202,20 +185,27 @@ void ptpd_netif_linearize_rx_timestamp(wr_timestamp_t * ts, int32_t dmtd_phase,
} }
/* Slow, but we don't care much... */ /* Slow, but we don't care much... */
static int wrap_copy_in(void *dst, struct sockq *q, size_t len) static int wrap_copy_in(void *dst, struct sockq *q, size_t len, size_t buflen)
{ {
char *dptr = dst; char *dptr = dst;
int i = len; int i;
net_verbose("copy_in: tail %d avail %d len %d\n", q->tail, q->avail,
len);
if (!buflen)
buflen = len;
net_verbose("copy_in: tail %d avail %d len %d (buf %d)\n",
q->tail, q->avail, len, buflen);
i = min(len, buflen);
while (i--) { while (i--) {
*dptr++ = q->buf[q->tail]; *dptr++ = q->buff[q->tail];
q->tail++; q->tail++;
if (q->tail == NET_SKBUF_SIZE) if (q->tail == q->size)
q->tail = 0; q->tail = 0;
} }
if (len > buflen) {
q->tail += len - buflen;
while (q->tail > q->size)
q->tail -= q->size;
}
return len; return len;
} }
...@@ -228,17 +218,16 @@ static int wrap_copy_out(struct sockq *q, void *src, size_t len) ...@@ -228,17 +218,16 @@ static int wrap_copy_out(struct sockq *q, void *src, size_t len)
len); len);
while (i--) { while (i--) {
q->buf[q->head++] = *sptr++; q->buff[q->head++] = *sptr++;
if (q->head == NET_SKBUF_SIZE) if (q->head == q->size)
q->head = 0; q->head = 0;
} }
return len; return len;
} }
int ptpd_netif_recvfrom(wr_socket_t * sock, wr_sockaddr_t * from, void *data, int ptpd_netif_recvfrom(struct wrpc_socket *s, struct wr_sockaddr *from, void *data,
size_t data_length, wr_timestamp_t * rx_timestamp) size_t data_length, struct wr_timestamp *rx_timestamp)
{ {
struct my_socket *s = (struct my_socket *)sock;
struct sockq *q = &s->queue; struct sockq *q = &s->queue;
uint16_t size; uint16_t size;
...@@ -252,10 +241,10 @@ int ptpd_netif_recvfrom(wr_socket_t * sock, wr_sockaddr_t * from, void *data, ...@@ -252,10 +241,10 @@ int ptpd_netif_recvfrom(wr_socket_t * sock, wr_sockaddr_t * from, void *data,
q->n--; q->n--;
q->avail += wrap_copy_in(&size, q, 2); q->avail += wrap_copy_in(&size, q, 2, 0);
q->avail += wrap_copy_in(&hdr, q, sizeof(struct ethhdr)); q->avail += wrap_copy_in(&hwts, q, sizeof(struct hw_timestamp), 0);
q->avail += wrap_copy_in(&hwts, q, sizeof(struct hw_timestamp)); q->avail += wrap_copy_in(&hdr, q, sizeof(struct ethhdr), 0);
q->avail += wrap_copy_in(data, q, min(size, data_length)); q->avail += wrap_copy_in(data, q, size, data_length);
from->ethertype = ntohs(hdr.ethtype); from->ethertype = ntohs(hdr.ethtype);
memcpy(from->mac, hdr.srcmac, 6); memcpy(from->mac, hdr.srcmac, 6);
...@@ -279,28 +268,34 @@ int ptpd_netif_recvfrom(wr_socket_t * sock, wr_sockaddr_t * from, void *data, ...@@ -279,28 +268,34 @@ int ptpd_netif_recvfrom(wr_socket_t * sock, wr_sockaddr_t * from, void *data,
REF_CLOCK_PERIOD_PS); REF_CLOCK_PERIOD_PS);
} }
net_verbose("%s: called from %p\n",
__func__, __builtin_return_address(0));
net_verbose("RX: Size %d tail %d Smac %x:%x:%x:%x:%x:%x\n", size, net_verbose("RX: Size %d tail %d Smac %x:%x:%x:%x:%x:%x\n", size,
q->tail, hdr.srcmac[0], hdr.srcmac[1], hdr.srcmac[2], q->tail, hdr.srcmac[0], hdr.srcmac[1], hdr.srcmac[2],
hdr.srcmac[3], hdr.srcmac[4], hdr.srcmac[5]); hdr.srcmac[3], hdr.srcmac[4], hdr.srcmac[5]);
return min(size - sizeof(struct ethhdr), data_length); return min(size, data_length);
} }
int ptpd_netif_sendto(wr_socket_t * sock, wr_sockaddr_t * to, void *data, int ptpd_netif_sendto(struct wrpc_socket * sock, struct wr_sockaddr *to, void *data,
size_t data_length, wr_timestamp_t * tx_timestamp) size_t data_length, struct wr_timestamp *tx_timestamp)
{ {
struct my_socket *s = (struct my_socket *)sock; struct wrpc_socket *s = (struct wrpc_socket *)sock;
struct hw_timestamp hwts; struct hw_timestamp hwts;
struct ethhdr hdr; struct ethhdr hdr;
int rval; int rval;
memcpy(hdr.dstmac, to->mac, 6); memcpy(hdr.dstmac, to->mac, 6);
memcpy(hdr.srcmac, s->local_mac, 6); memcpy(hdr.srcmac, s->local_mac, 6);
hdr.ethtype = to->ethertype; hdr.ethtype = sock->bind_addr.ethertype;
net_verbose("TX: socket %04x:%04x, len %i\n",
ntohs(s->bind_addr.ethertype),
s->bind_addr.udpport,
data_length);
rval = rval =
minic_tx_frame((uint8_t *) & hdr, (uint8_t *) data, minic_tx_frame((uint8_t *) & hdr, (uint8_t *) data,
data_length + ETH_HEADER_SIZE, &hwts); data_length, &hwts);
if (tx_timestamp) { if (tx_timestamp) {
...@@ -315,30 +310,46 @@ int ptpd_netif_sendto(wr_socket_t * sock, wr_sockaddr_t * to, void *data, ...@@ -315,30 +310,46 @@ int ptpd_netif_sendto(wr_socket_t * sock, wr_sockaddr_t * to, void *data,
void update_rx_queues() void update_rx_queues()
{ {
struct my_socket *s = NULL; struct wrpc_socket *s = NULL;
struct sockq *q; struct sockq *q;
struct hw_timestamp hwts; struct hw_timestamp hwts;
static struct ethhdr hdr; static struct ethhdr hdr;
int recvd, i, q_required; int recvd, i, q_required;
static uint8_t payload[NET_SKBUF_SIZE - 32]; static uint8_t payload[NET_MAX_SKBUF_SIZE - 32];
uint16_t size; uint16_t size, port;
recvd = recvd =
minic_rx_frame((uint8_t *) & hdr, payload, NET_SKBUF_SIZE - 32, minic_rx_frame((uint8_t *) & hdr, payload, sizeof(payload),
&hwts); &hwts);
if (recvd <= 0) /* No data received? */ if (recvd <= 0) /* No data received? */
return; return;
for (i = 0; i < NET_MAX_SOCKETS; i++) { for (i = 0; i < ARRAY_SIZE(socks); i++) {
s = &socks[i]; s = socks[i];
if (s->in_use && !memcmp(hdr.dstmac, s->bind_addr.mac, 6) if (!s)
&& hdr.ethtype == s->bind_addr.ethertype) continue;
break; /*they match */ if (memcmp(hdr.dstmac, s->bind_addr.mac, 6))
s = NULL; continue;
if (hdr.ethtype != s->bind_addr.ethertype)
continue;
if (s->bind_addr.udpport == 0)
break; /* raw socket: match */
/* Now make IP/UDP checks */
if (payload[IP_VERSION] != 0x45)
continue;
if (payload[IP_PROTOCOL] != 17)
continue;
port = payload[UDP_DPORT] << 8 | payload[UDP_DPORT + 1];
if (port != s->bind_addr.udpport)
continue;
break; /* udp match */
} }
if (!s) { if (i == ARRAY_SIZE(socks)) {
net_verbose("%s: could not find socket for packet\n", net_verbose("%s: could not find socket for packet\n",
__FUNCTION__); __FUNCTION__);
return; return;
...@@ -358,8 +369,8 @@ void update_rx_queues() ...@@ -358,8 +369,8 @@ void update_rx_queues()
size = recvd; size = recvd;
q->avail -= wrap_copy_out(q, &size, 2); q->avail -= wrap_copy_out(q, &size, 2);
q->avail -= wrap_copy_out(q, &hdr, sizeof(struct ethhdr));
q->avail -= wrap_copy_out(q, &hwts, sizeof(struct hw_timestamp)); q->avail -= wrap_copy_out(q, &hwts, sizeof(struct hw_timestamp));
q->avail -= wrap_copy_out(q, &hdr, sizeof(struct ethhdr));
q->avail -= wrap_copy_out(q, payload, size); q->avail -= wrap_copy_out(q, payload, size);
q->n++; q->n++;
...@@ -367,6 +378,9 @@ void update_rx_queues() ...@@ -367,6 +378,9 @@ void update_rx_queues()
q->head, hdr.srcmac[0], hdr.srcmac[1], hdr.srcmac[2], q->head, hdr.srcmac[0], hdr.srcmac[1], hdr.srcmac[2],
hdr.srcmac[3], hdr.srcmac[4], hdr.srcmac[5]); hdr.srcmac[3], hdr.srcmac[4], hdr.srcmac[5]);
net_verbose("%s: saved packet to queue [avail %d n %d size %d]\n", net_verbose("%s: saved packet to socket %04x:%04x "
__FUNCTION__, q->avail, q->n, q_required); "[avail %d n %d size %d]\n", __FUNCTION__,
ntohs(s->bind_addr.ethertype),
s->bind_addr.udpport,
q->avail, q->n, q_required);
} }
#include <string.h>
#include <wrc.h>
#include <wrpc.h>
#include "endpoint.h"
#include "minic.h"
#include "shell.h"
#include "pps_gen.h"
#include "ipv4.h"
/* syslog: a tx-only socket: no queue is there */
static struct wrpc_socket __static_syslog_socket = {
.queue.buff = NULL,
.queue.size = 0,
};
static struct wrpc_socket *syslog_socket;
static struct wr_udp_addr syslog_addr;
unsigned char syslog_mac[6];
static uint32_t tics, tics_zero;
void syslog_init(void)
{
syslog_socket = ptpd_netif_create_socket(&__static_syslog_socket, NULL,
PTPD_SOCK_UDP, 514 /* time */);
syslog_addr.sport = syslog_addr.dport = htons(514);
tics_zero = timer_get_tics();
}
static int cmd_syslog(const char *args[])
{
char b1[32], b2[32];
if (args[0] && !strcmp(args[0], "off")) {
syslog_addr.daddr = 0;
return 0;
}
if (!args[1]) {
pp_printf("use: syslog <ipaddr> <macaddr> (or just \"off\"\n");
return -1;
}
decode_ip(args[0], (void *)&syslog_addr.daddr);
decode_mac(args[1], syslog_mac);
pp_printf("Syslog parameters: %s, %s\n",
format_ip(b1, (void *)&syslog_addr.daddr),
format_mac(b2, syslog_mac));
tics = 0; /* send the first frame immediately to the new host */
return 0;
}
DEFINE_WRC_COMMAND(mac) = {
.name = "syslog",
.exec = cmd_syslog,
};
void syslog_poll(int l_status)
{
struct wr_sockaddr addr;
char buf[256];
char b1[32], b2[32];
unsigned char mac[6];
unsigned char ip[4];
uint64_t secs;
static uint32_t down_tics;
int len = 0;
if (needIP)
return;
if (!syslog_addr.daddr)
return;
if (!tics) {
/* first time ever, or new syslog server */
tics = timer_get_tics() - 1;
shw_pps_gen_get_time(&secs, NULL);
get_mac_addr(mac);
getIP(ip);
len = pp_sprintf(buf + UDP_END, /* 8 == user + 6 == info */
"<14> %s %s (%s) Node up "
"since %i seconds\n",
format_time(secs, TIME_FORMAT_SYSLOG),
format_ip(b1, ip), format_mac(b2, mac),
(tics - tics_zero) / 1000);
goto send;
}
if (l_status == LINK_WENT_DOWN)
down_tics = timer_get_tics();
if (l_status == LINK_UP && down_tics) {
down_tics = timer_get_tics() - down_tics;
shw_pps_gen_get_time(&secs, NULL);
getIP(ip);
len = pp_sprintf(buf + UDP_END, /* 8 == user + 6 == info */
"<14> %s %s Link up after %i.%03i s\n",
format_time(secs, TIME_FORMAT_SYSLOG),
format_ip(b1, ip),
down_tics / 1000, down_tics % 1000);
down_tics = 0;
goto send;
}
return;
send:
len += UDP_END;
memcpy(&syslog_addr.saddr, ip, 4);
fill_udp((void *)buf, len, &syslog_addr);
memcpy(&addr.mac, syslog_mac, 6);
ptpd_netif_sendto(syslog_socket, &addr, buf, len, 0);
}
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2016 GSI (www.gsi.de)
* Author: Alessandro Rubini <a.rubini@gsi.de>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <string.h>
#include "ipv4.h"
#include "ptpd_netif.h"
void fill_udp(uint8_t * buf, int len, struct wr_udp_addr *uaddr)
{
unsigned short sum;
struct wr_udp_addr addr;
/* if there is no user-provided uaddr, we are replying */
if (!uaddr) {
memcpy(&addr.daddr, buf + IP_SOURCE, 4);
memcpy(&addr.saddr, buf + IP_DEST, 4);
memcpy(&addr.dport, buf + UDP_SPORT, 2);
memcpy(&addr.sport, buf + UDP_DPORT, 2);
uaddr = &addr;
}
// ------------ UDP -------------
memcpy(buf + UDP_VIRT_SADDR, &uaddr->saddr, 4);
memcpy(buf + UDP_VIRT_DADDR, &uaddr->daddr, 4);
buf[UDP_VIRT_ZEROS] = 0;
buf[UDP_VIRT_PROTO] = 0x11; /* UDP */
buf[UDP_VIRT_LENGTH] = (len - IP_END) >> 8;
buf[UDP_VIRT_LENGTH + 1] = (len - IP_END) & 0xff;
memcpy(buf + UDP_SPORT, &uaddr->sport, 2);
memcpy(buf + UDP_DPORT, &uaddr->dport, 2);
buf[UDP_LENGTH] = (len - IP_END) >> 8;
buf[UDP_LENGTH + 1] = (len - IP_END) & 0xff;
buf[UDP_CHECKSUM] = 0;
buf[UDP_CHECKSUM + 1] = 0;
sum =
ipv4_checksum((unsigned short *)(buf + UDP_VIRT_SADDR),
(len - 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] = len >> 8;
buf[IP_LEN + 1] = len & 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;
memcpy(buf + IP_SOURCE, &uaddr->saddr, 4);
memcpy(buf + IP_DEST, &uaddr->daddr, 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;
return;
}
...@@ -41,7 +41,7 @@ static const int _ytab[2][12] = { ...@@ -41,7 +41,7 @@ static const int _ytab[2][12] = {
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
}; };
char *format_time(uint64_t sec) char *format_time(uint64_t sec, int format)
{ {
struct tm t; struct tm t;
static char buf[64]; static char buf[64];
...@@ -69,9 +69,23 @@ char *format_time(uint64_t sec) ...@@ -69,9 +69,23 @@ char *format_time(uint64_t sec)
t.tm_mday = dayno + 1; t.tm_mday = dayno + 1;
t.tm_isdst = 0; t.tm_isdst = 0;
sprintf(buf, "%s, %s %d, %d, %02d:%02d:%02d", _days[t.tm_wday], switch(format) {
_months[t.tm_mon], t.tm_mday, t.tm_year + YEAR0, t.tm_hour, case TIME_FORMAT_LEGACY:
t.tm_min, t.tm_sec); default:
sprintf(buf, "%s, %s %d, %d, %02d:%02d:%02d", _days[t.tm_wday],
_months[t.tm_mon], t.tm_mday, t.tm_year + YEAR0,
t.tm_hour, t.tm_min, t.tm_sec);
break;
case TIME_FORMAT_SYSLOG:
sprintf(buf, "%s %2d %02d:%02d:%02d", _months[t.tm_mon],
t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
break;
case TIME_FORMAT_SORTED:
sprintf(buf, "%4d-%02d-%02d-%02d:%02d:%02d",
t.tm_year + YEAR0, t.tm_mon + 1, t.tm_mday,
t.tm_hour, t.tm_min, t.tm_sec);
break;
}
return buf; return buf;
} }
......
...@@ -110,7 +110,7 @@ void wrc_mon_gui(void) ...@@ -110,7 +110,7 @@ void wrc_mon_gui(void)
shw_pps_gen_get_time(&sec, &nsec); shw_pps_gen_get_time(&sec, &nsec);
cprintf(C_BLUE, "\n\nTAI Time: "); cprintf(C_BLUE, "\n\nTAI Time: ");
cprintf(C_WHITE, "%s", format_time(sec)); cprintf(C_WHITE, "%s", format_time(sec, TIME_FORMAT_LEGACY));
/*show_ports */ /*show_ports */
wrpc_get_port_state(&state, NULL); wrpc_get_port_state(&state, NULL);
......
ppsi @ 43635331
Subproject commit b203cc96df8d4008fe311deaf7baab8e555d5c96 Subproject commit 43635331c54fa906bf54ad75e3087e336bdc7799
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include "shell.h" #include "shell.h"
#include "../lib/ipv4.h" #include "../lib/ipv4.h"
static void decode_ip(const char *str, unsigned char *ip) void decode_ip(const char *str, unsigned char *ip)
{ {
int i, x; int i, x;
...@@ -28,9 +28,17 @@ static void decode_ip(const char *str, unsigned char *ip) ...@@ -28,9 +28,17 @@ static void decode_ip(const char *str, unsigned char *ip)
} }
} }
char *format_ip(char *s, const unsigned char *ip)
{
pp_sprintf(s, "%d.%d.%d.%d",
ip[0], ip[1], ip[2], ip[3]);
return s;
}
static int cmd_ip(const char *args[]) static int cmd_ip(const char *args[])
{ {
unsigned char ip[4]; unsigned char ip[4];
char buf[20];
if (!args[0] || !strcasecmp(args[0], "get")) { if (!args[0] || !strcasecmp(args[0], "get")) {
getIP(ip); getIP(ip);
...@@ -44,8 +52,7 @@ static int cmd_ip(const char *args[]) ...@@ -44,8 +52,7 @@ static int cmd_ip(const char *args[])
if (needIP) { if (needIP) {
pp_printf("IP-address: in training\n"); pp_printf("IP-address: in training\n");
} else { } else {
pp_printf("IP-address: %d.%d.%d.%d\n", pp_printf("IP-address: %s\n", format_ip(buf, ip));
ip[0], ip[1], ip[2], ip[3]);
} }
return 0; return 0;
} }
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include "endpoint.h" #include "endpoint.h"
#include "../lib/ipv4.h" #include "../lib/ipv4.h"
static void decode_mac(const char *str, unsigned char *mac) void decode_mac(const char *str, unsigned char *mac)
{ {
int i, x; int i, x;
...@@ -30,9 +30,18 @@ static void decode_mac(const char *str, unsigned char *mac) ...@@ -30,9 +30,18 @@ static void decode_mac(const char *str, unsigned char *mac)
} }
} }
char *format_mac(char *s, const unsigned char *mac)
{
pp_sprintf(s, "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return s;
}
static int cmd_mac(const char *args[]) static int cmd_mac(const char *args[])
{ {
unsigned char mac[6]; unsigned char mac[6];
char buf[32];
if (!args[0] || !strcasecmp(args[0], "get")) { if (!args[0] || !strcasecmp(args[0], "get")) {
/* get current MAC */ /* get current MAC */
...@@ -52,8 +61,7 @@ static int cmd_mac(const char *args[]) ...@@ -52,8 +61,7 @@ static int cmd_mac(const char *args[])
return -EINVAL; return -EINVAL;
} }
pp_printf("MAC-address: %02x:%02x:%02x:%02x:%02x:%02x\n", pp_printf("MAC-address: %s\n", format_mac(buf, mac));
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return 0; return 0;
} }
......
...@@ -53,7 +53,9 @@ static int cmd_time(const char *args[]) ...@@ -53,7 +53,9 @@ static int cmd_time(const char *args[])
return 0; return 0;
} }
pp_printf("%s +%d nanoseconds.\n", format_time(sec), nsec); /* fixme: clock freq is not always 125 MHz */ pp_printf("%s +%d nanoseconds.\n",
format_time(sec, TIME_FORMAT_LEGACY), nsec);
/* fixme: clock freq is not always 125 MHz */
return 0; return 0;
} }
......
...@@ -409,6 +409,7 @@ void pfilter_init(int mode, char *fname) ...@@ -409,6 +409,7 @@ void pfilter_init(int mode, char *fname)
pfilter_cmp(18, 0x0044, 0xffff, MOV, PORT_UDP_HOST); /* bootpc */ pfilter_cmp(18, 0x0044, 0xffff, MOV, PORT_UDP_HOST); /* bootpc */
pfilter_cmp(18, 0x013f, 0xffff, OR, PORT_UDP_HOST); /* ptp event */ pfilter_cmp(18, 0x013f, 0xffff, OR, PORT_UDP_HOST); /* ptp event */
pfilter_cmp(18, 0x0140, 0xffff, OR, PORT_UDP_HOST); /* ptp general */ pfilter_cmp(18, 0x0140, 0xffff, OR, PORT_UDP_HOST); /* ptp general */
pfilter_cmp(18, 0x0025, 0xffff, OR, PORT_UDP_HOST); /* rdate */
/* The CPU gets those ports in a proper UDP frame, plus the previous selections */ /* The CPU gets those ports in a proper UDP frame, plus the previous selections */
pfilter_logic3(FRAME_FOR_CPU, FRAME_UDP, AND, PORT_UDP_HOST, OR, FRAME_FOR_CPU); pfilter_logic3(FRAME_FOR_CPU, FRAME_UDP, AND, PORT_UDP_HOST, OR, FRAME_FOR_CPU);
......
...@@ -96,11 +96,6 @@ static void wrc_initialize(void) ...@@ -96,11 +96,6 @@ static void wrc_initialize(void)
} }
} }
#define LINK_WENT_UP 1
#define LINK_WENT_DOWN 2
#define LINK_UP 3
#define LINK_DOWN 4
static int wrc_check_link(void) static int wrc_check_link(void)
{ {
static int prev_link_state = -1; static int prev_link_state = -1;
...@@ -184,24 +179,20 @@ int main(void) ...@@ -184,24 +179,20 @@ int main(void)
} }
switch (l_status) { switch (l_status) {
case LINK_WENT_DOWN:
if (wrc_ptp_get_mode() == WRC_MODE_SLAVE) {
spll_init(SPLL_MODE_FREE_RUNNING_MASTER, 0, 1);
shw_pps_gen_enable_output(0);
}
/* fall through */
case LINK_WENT_UP: case LINK_WENT_UP:
needIP = 1;
break;
case LINK_UP: case LINK_UP:
update_rx_queues(); update_rx_queues();
if (HAS_IP) { if (HAS_IP) {
ipv4_poll(); ipv4_poll(l_status);
arp_poll(); arp_poll();
} }
break; break;
case LINK_WENT_DOWN:
if (wrc_ptp_get_mode() == WRC_MODE_SLAVE) {
spll_init(SPLL_MODE_FREE_RUNNING_MASTER, 0, 1);
shw_pps_gen_enable_output(0);
}
break;
} }
ui_update(); ui_update();
......
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