Commit 512ec393 authored by Aurelio Colosimo's avatar Aurelio Colosimo Committed by Alessandro Rubini

libposix/net.c and libptpnetif/ptpd_netif.h moved from ptp-noposix to wrpc-sw

This two files where just copied from ptp-noposix
script/Lindent was run on them.

ptpd_netif.h has not been removed from ptp-noposix, because hosted compilation
needs it.
Signed-off-by: Aurelio Colosimo's avatarAurelio Colosimo <aurelio@aureliocolosimo.it>
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent fb51f37c
......@@ -63,8 +63,7 @@ obj-$(CONFIG_PTP_NOPOSIX) += $(PTP_NOPOSIX)/PTPWRd/arith.o \
$(PTP_NOPOSIX)/PTPWRd/protocol.o \
$(PTP_NOPOSIX)/PTPWRd/wr_protocol.o \
$(PTP_NOPOSIX)/libposix/freestanding-startup.o \
$(PTP_NOPOSIX)/libposix/freestanding-wrapper.o \
$(PTP_NOPOSIX)/libposix/net.o
$(PTP_NOPOSIX)/libposix/freestanding-wrapper.o
CFLAGS_PLATFORM = -mmultiply-enabled -mbarrel-shift-enabled
LDFLAGS_PLATFORM = -mmultiply-enabled -mbarrel-shift-enabled \
......
// Network API for WR-PTPd
#ifndef __PTPD_NETIF_H
#define __PTPD_NETIF_H
#include <stdio.h>
//#include <inttypes.h>
#define PTPD_SOCK_RAW_ETHERNET 1
#define PTPD_SOCK_UDP 2
#define PTPD_FLAGS_MULTICAST 0x1
// error codes (to be extended)
#define PTPD_NETIF_READY 1
#define PTPD_NETIF_OK 0
#define PTPD_NETIF_ERROR -1
#define PTPD_NETIF_NOT_READY -2
#define PTPD_NETIF_NOT_FOUND -3
// GCC-specific
#define PACKED __attribute__((packed))
#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
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
typedef struct {
// Network interface name (eth0, ...)
char if_name[IFACE_NAME_LEN];
// Socket family (RAW ethernet/UDP)
int family;
// MAC address
mac_addr_t mac;
// Destination MASC address, filled by recvfrom() function on interfaces bound to multiple addresses
mac_addr_t mac_dest;
// IP address
ipv4_addr_t ip;
// UDP port
uint16_t port;
// RAW ethertype
uint16_t ethertype;
// physical port to bind socket to
uint16_t physical_port;
} wr_sockaddr_t;
PACKED struct _wr_timestamp {
// Seconds
int64_t sec;
// Nanoseconds
int32_t nsec;
// Phase (in picoseconds), linearized for receive timestamps, zero for send timestamps
int32_t phase; // phase(picoseconds)
/* Raw time (non-linearized) for debugging purposes */
int32_t raw_phase;
int32_t raw_nsec;
int32_t raw_ahead;
// correctness flag: when 0, the timestamp MAY be incorrect (e.g. generated during timebase adjustment)
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();
// Creates UDP or Ethernet RAW socket (determined by sock_type) bound to bind_addr. If PTPD_FLAG_MULTICAST is set, the socket is
// automatically added to multicast group. User can specify physical_port field to bind the socket to specific switch port only.
wr_socket_t *ptpd_netif_create_socket(int sock_type, int flags,
wr_sockaddr_t * bind_addr);
// Sends a UDP/RAW packet (data, data_length) to address provided in wr_sockaddr_t.
// 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
// 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,
size_t data_length, wr_timestamp_t * tx_ts);
// Receives an UDP/RAW packet. Data is written to (data) and length is returned. 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).
int ptpd_netif_recvfrom(wr_socket_t * sock, wr_sockaddr_t * from, void *data,
size_t data_length, wr_timestamp_t * rx_timestamp);
// Closes the socket.
int ptpd_netif_close_socket(wr_socket_t * sock);
int ptpd_netif_poll(wr_socket_t *);
int ptpd_netif_get_hw_addr(wr_socket_t * sock, mac_addr_t * mac);
/*
* Function start HW locking of freq on WR Slave
* return:
* PTPD_NETIF_ERROR - locking not started
* PTPD_NETIF_OK - locking started
*/
int ptpd_netif_locking_enable(int txrx, const char *ifaceName, int priority);
/*
*
* return:
*
* PTPD_NETIF_OK - locking started
*/
int ptpd_netif_locking_disable(int txrx, const char *ifaceName, int priority);
int ptpd_netif_locking_poll(int txrx, const char *ifaceName, int priority);
/*
* Function turns on calibration (measurement of delay)
* Tx or Rx depending on the txrx param
* return:
* PTPD_NETIF_NOT_READY - if there is calibratin going on on another port
* PTPD_NETIF_OK - calibration started
*/
int ptpd_netif_calibrating_enable(int txrx, const char *ifaceName);
/*
* Function turns off calibration (measurement of delay)
* Tx or Rx depending on the txrx param
* return:
* PTPD_NETIF_ERROR - if there is calibratin going on on another port
* PTPD_NETIF_OK - calibration started
*/
int ptpd_netif_calibrating_disable(int txrx, const char *ifaceName);
/*
* Function checks if Rx/Tx (depending on the param) calibration is finished
* if finished, returns measured delay in delta
* return:
*
* PTPD_NETIF_OK - locking started
*/
int ptpd_netif_calibrating_poll(int txrx, const char *ifaceName,
uint64_t * delta);
/*
* Function turns on calibration pattern.
* return:
* PTPD_NETIF_NOT_READY - if WRSW is busy with calibration on other switch or error occured
* PTPD_NETIF_OK - calibration started
*/
int ptpd_netif_calibration_pattern_enable(const char *ifaceName,
unsigned int calibrationPeriod,
unsigned int calibrationPattern,
unsigned int calibrationPatternLen);
/*
* Function turns off calibration pattern
* return:
* PTPD_NETIF_ERROR - turning off not successful
* PTPD_NETIF_OK - turning off successful
*/
int ptpd_netif_calibration_pattern_disable(const char *ifaceName);
/*
* Function reads calibration data if it's available, used at the beginning of PTPWRd to check if
* HW knows already the interface's deltax, and therefore no need for calibration
* return:
* PTPD_NETIF_NOT_FOUND - if deltas are not known
* PTPD_NETIF_OK - if deltas are known, in such case, deltaTx and deltaRx have valid data
*/
int ptpd_netif_read_calibration_data(const char *ifaceName, uint64_t * deltaTx,
uint64_t * deltaRx, int32_t * fix_alpha,
int32_t * clock_period);
int ptpd_netif_select(wr_socket_t *);
int ptpd_netif_get_hw_addr(wr_socket_t * sock, mac_addr_t * mac);
/*
* Function reads state of the given port (interface in our case), if the port is up, everything is OK, otherwise ERROR
* return:
* PTPD_NETIF_ERROR - if the port is down
* PTPD_NETIF_OK - if the port is up
*/
int ptpd_netif_get_port_state(const char *ifaceName);
/*
* Function looks for a port (interface) for the port number 'number'
* it will return in the argument ifname the port name
* return:
* PTPD_NETIF_ERROR - port not found
* PTPD_NETIF_OK - if the port found
*/
int ptpd_netif_get_ifName(char *ifname, int number);
/* Returns the millisecond "tics" counter value */
uint64_t ptpd_netif_get_msec_tics();
/*
* Function detects external source lock,
*
* return:
* HEXP_EXTSRC_STATUS_LOCKED 0
* HEXP_LOCK_STATUS_BUSY 1
* HEXP_EXTSRC_STATUS_NOSRC 2
*/
int ptpd_netif_extsrc_detection();
/* Timebase adjustment functions - the servo should not call the HAL directly */
int ptpd_netif_adjust_counters(int64_t adjust_sec, int32_t adjust_nsec);
int ptpd_netif_adjust_phase(int32_t phase_ps);
int ptpd_netif_adjust_in_progress();
int ptpd_netif_get_dmtd_phase(wr_socket_t * sock, int32_t * phase);
void ptpd_netif_linearize_rx_timestamp(wr_timestamp_t * ts, int32_t dmtd_phase,
int cntr_ahead, int transition_point,
int clock_period);
int ptpd_netif_enable_timing_output(int enable);
int ptpd_netif_enable_phase_tracking(const char *if_name);
#endif
obj-$(CONFIG_MPRINTF) += lib/mprintf.o
obj-y += lib/util.o lib/atoi.o
obj-y += lib/net.o
obj-$(CONFIG_ETHERBONE) += lib/arp.o lib/icmp.o lib/ipv4.o lib/bootp.o
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "hal_exports.h"
#include "ptpd_netif.h"
#include "board.h"
#include "pps_gen.h"
#include "minic.h"
#include "softpll_ng.h"
#define min(x,y) ((x) < (y) ? (x) : (y))
__attribute__ ((packed))
struct ethhdr {
uint8_t dstmac[6];
uint8_t srcmac[6];
uint16_t ethtype;
};
struct timeout {
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;
}
int ptpd_netif_get_hw_addr(wr_socket_t * sock, mac_addr_t * mac)
{
get_mac_addr((uint8_t *) mac);
return 0;
}
void ptpd_netif_set_phase_transition(wr_socket_t * sock, int phase)
{
struct my_socket *s = (struct my_socket *)sock;
s->phase_transition = phase;
}
wr_socket_t *ptpd_netif_create_socket(int sock_type, int flags,
wr_sockaddr_t * bind_addr)
{
int i;
hexp_port_state_t pstate;
struct my_socket *sock;
/* Look for the first available socket. */
for (sock = NULL, i = 0; i < NET_MAX_SOCKETS; i++)
if (!socks[i].in_use) {
sock = &socks[i];
break;
}
if (!sock) {
TRACE_WRAP("No sockets left.\n");
return NULL;
}
if (sock_type != PTPD_SOCK_RAW_ETHERNET)
return NULL;
if (halexp_get_port_state(&pstate, bind_addr->if_name) < 0)
return NULL;
memcpy(&sock->bind_addr, bind_addr, sizeof(wr_sockaddr_t));
/*get mac from endpoint */
get_mac_addr(sock->local_mac);
sock->phase_transition = pstate.t2_phase_transition;
sock->dmtd_phase = pstate.phase_val;
/*packet queue */
sock->queue.head = sock->queue.tail = 0;
sock->queue.avail = NET_SKBUF_SIZE;
sock->queue.n = 0;
sock->in_use = 1;
return (wr_socket_t *) (sock);
}
int ptpd_netif_close_socket(wr_socket_t * sock)
{
struct my_socket *s = (struct my_socket *)sock;
if (s)
s->in_use = 0;
return 0;
}
static inline int inside_range(int min, int max, int x)
{
if (min < max)
return (x >= min && x <= max);
else
return (x <= max || x >= min);
}
void ptpd_netif_linearize_rx_timestamp(wr_timestamp_t * ts, int32_t dmtd_phase,
int cntr_ahead, int transition_point,
int clock_period)
{
int trip_lo, trip_hi;
int phase;
// "phase" transition: DMTD output value (in picoseconds)
// at which the transition of rising edge
// TS counter will appear
ts->raw_phase = dmtd_phase;
phase = clock_period - 1 - dmtd_phase;
// calculate the range within which falling edge timestamp is stable
// (no possible transitions)
trip_lo = transition_point - clock_period / 4;
if (trip_lo < 0)
trip_lo += clock_period;
trip_hi = transition_point + clock_period / 4;
if (trip_hi >= clock_period)
trip_hi -= clock_period;
if (inside_range(trip_lo, trip_hi, phase)) {
// We are within +- 25% range of transition area of
// rising counter. Take the falling edge counter value as the
// "reliable" one. cntr_ahead will be 1 when the rising edge
//counter is 1 tick ahead of the falling edge counter
ts->nsec -= cntr_ahead ? (clock_period / 1000) : 0;
// check if the phase is before the counter transition value
// and eventually increase the counter by 1 to simulate a
// timestamp transition exactly at s->phase_transition
//DMTD phase value
if (inside_range(trip_lo, transition_point, phase))
ts->nsec += clock_period / 1000;
}
ts->phase = phase - transition_point - 1;
if (ts->phase < 0)
ts->phase += clock_period;
ts->phase = clock_period - 1 - ts->phase;
}
/* Slow, but we don't care much... */
static int wrap_copy_in(void *dst, struct sockq *q, size_t len)
{
char *dptr = dst;
int i = len;
TRACE_WRAP("copy_in: tail %d avail %d len %d\n", q->tail, q->avail,
len);
while (i--) {
*dptr++ = q->buf[q->tail];
q->tail++;
if (q->tail == NET_SKBUF_SIZE)
q->tail = 0;
}
return len;
}
static int wrap_copy_out(struct sockq *q, void *src, size_t len)
{
char *sptr = src;
int i = len;
TRACE_WRAP("copy_out: head %d avail %d len %d\n", q->head, q->avail,
len);
while (i--) {
q->buf[q->head++] = *sptr++;
if (q->head == NET_SKBUF_SIZE)
q->head = 0;
}
return len;
}
int ptpd_netif_recvfrom(wr_socket_t * sock, wr_sockaddr_t * from, void *data,
size_t data_length, wr_timestamp_t * rx_timestamp)
{
struct my_socket *s = (struct my_socket *)sock;
struct sockq *q = &s->queue;
uint16_t size;
struct ethhdr hdr;
struct hw_timestamp hwts;
/*check if there is something to fetch */
if (!q->n)
return 0;
q->n--;
q->avail += wrap_copy_in(&size, q, 2);
q->avail += wrap_copy_in(&hdr, q, sizeof(struct ethhdr));
q->avail += wrap_copy_in(&hwts, q, sizeof(struct hw_timestamp));
q->avail += wrap_copy_in(data, q, min(size, data_length));
from->ethertype = ntohs(hdr.ethtype);
memcpy(from->mac, hdr.srcmac, 6);
memcpy(from->mac_dest, hdr.dstmac, 6);
if (rx_timestamp) {
rx_timestamp->raw_nsec = hwts.nsec;
rx_timestamp->raw_ahead = hwts.ahead;
spll_read_ptracker(0, &rx_timestamp->raw_phase, NULL);
rx_timestamp->sec = hwts.sec;
rx_timestamp->nsec = hwts.nsec;
rx_timestamp->phase = 0;
rx_timestamp->correct = hwts.valid;
ptpd_netif_linearize_rx_timestamp(rx_timestamp,
rx_timestamp->raw_phase,
hwts.ahead,
s->phase_transition,
REF_CLOCK_PERIOD_PS);
}
TRACE_WRAP("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],
hdr.srcmac[3], hdr.srcmac[4], hdr.srcmac[5]);
/* TRACE_WRAP("%s: received data from %02x:%02x:%02x:%02x:%02x:%02x to %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, from->mac[0],from->mac[1],from->mac[2],from->mac[3],
from->mac[4],from->mac[5],from->mac[6],from->mac[7],
from->mac_dest[0],from->mac_dest[1],from->mac_dest[2],from->mac_dest[3],
from->mac_dest[4],from->mac_dest[5],from->mac_dest[6],from->mac_dest[7]);*/
return min(size, data_length);
return 0;
}
int ptpd_netif_select(wr_socket_t * wrSock)
{
return 0;
}
int ptpd_netif_sendto(wr_socket_t * sock, wr_sockaddr_t * to, void *data,
size_t data_length, wr_timestamp_t * tx_timestamp)
{
struct my_socket *s = (struct my_socket *)sock;
struct hw_timestamp hwts;
struct ethhdr hdr;
int rval;
memcpy(hdr.dstmac, to->mac, 6);
memcpy(hdr.srcmac, s->local_mac, 6);
hdr.ethtype = to->ethertype;
rval =
minic_tx_frame((uint8_t *) & hdr, (uint8_t *) data,
data_length + ETH_HEADER_SIZE, &hwts);
if (tx_timestamp) {
tx_timestamp->sec = hwts.sec;
tx_timestamp->nsec = hwts.nsec;
tx_timestamp->phase = 0;
tx_timestamp->correct = hwts.valid;
}
return rval;
}
void update_rx_queues()
{
struct my_socket *s = NULL;
struct sockq *q;
struct hw_timestamp hwts;
static struct ethhdr hdr;
int recvd, i, q_required;
static uint8_t payload[NET_SKBUF_SIZE - 32];
uint16_t size;
recvd =
minic_rx_frame((uint8_t *) & hdr, payload, NET_SKBUF_SIZE - 32,
&hwts);
if (recvd <= 0) /* No data received? */
return;
for (i = 0; i < NET_MAX_SOCKETS; i++) {
s = &socks[i];
if (s->in_use && !memcmp(hdr.dstmac, s->bind_addr.mac, 6)
&& hdr.ethtype == s->bind_addr.ethertype)
break; /*they match */
s = NULL;
}
if (!s) {
TRACE_WRAP("%s: could not find socket for packet\n",
__FUNCTION__);
return;
}
q = &s->queue;
q_required =
sizeof(struct ethhdr) + recvd + sizeof(struct hw_timestamp) + 2;
if (q->avail < q_required) {
TRACE_WRAP
("%s: queue for socket full; [avail %d required %d]\n",
__FUNCTION__, q->avail, q_required);
return;
}
size = recvd;
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, payload, size);
q->n++;
TRACE_WRAP("Q: Size %d head %d Smac %x:%x:%x:%x:%x:%x\n", recvd,
q->head, hdr.srcmac[0], hdr.srcmac[1], hdr.srcmac[2],
hdr.srcmac[3], hdr.srcmac[4], hdr.srcmac[5]);
TRACE_WRAP("%s: saved packet to queue [avail %d n %d size %d]\n",
__FUNCTION__, q->avail, q->n, q_required);
}
ptp-noposix @ 79a7beb2
Subproject commit d09236750dde5346ca38646a9ae7b1124e9e1abd
Subproject commit 79a7beb2d41bc150f888292d0f7502c81d02724a
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