Commit 75eb932e authored by Aurelio Colosimo's avatar Aurelio Colosimo

arch-gnu-linux: main loop handling multilink

posix_main_loop now gets a struct pp_globals ptr and simultaneously
handles all configured links. posix_net_check_pkt has been changed too,
in order to perform a global select on all fd's.

This patch is temporary since it may need debug & test.
Signed-off-by: Aurelio Colosimo's avatarAurelio Colosimo <aurelio@aureliocolosimo.it>
parent 3ea28e22
......@@ -13,61 +13,98 @@
#include <ppsi/ppsi.h>
#include "posix.h"
/* Call pp_state_machine for each instance. To be called periodically,
* when no packets are incoming */
static int run_all_state_machines(struct pp_globals *ppg)
{
int j;
int delay_ms = 0, delay_ms_j;
for (j = 0; j < ppg->nlinks; j++) {
struct pp_instance *ppi = &ppg->pp_instances[j];
delay_ms_j = pp_state_machine(ppi, NULL, 0);
/* delay_ms is the least delay_ms among all instances */
if (delay_ms == 0)
delay_ms = delay_ms_j;
else
delay_ms = delay_ms_j < delay_ms ? delay_ms_j : delay_ms;
}
return delay_ms;
}
void posix_main_loop(struct pp_globals *ppg)
{
int delay_ms;
struct pp_instance *ppi;
int delay_ms;
int j;
/* Initialize each link's state machine */
for (j = 0; j < ppg->nlinks; j++) {
ppi = &ppg->pp_instances[j];
/*
* If we are sending or receiving raw ethernet frames,
* the ptp payload is one-eth-header bytes into the frame
*/
if (ppi->ethernet_mode)
NP(ppi)->ptp_offset = ETH_HLEN;
/*
* The main loop here is based on select. While we are not
* doing anything else but the protocol, this allows extra stuff
* to fit.
*/
ppi->is_new_state = 1;
}
delay_ms = run_all_state_machines(ppg);
ppi = &ppg->pp_instances[0];
/*
* If we are sending or receiving raw ethernet frames,
* the ptp payload is one-eth-header bytes into the frame
*/
if (ppi->ethernet_mode)
NP(ppi)->ptp_offset = ETH_HLEN;
/*
* The main loop here is based on select. While we are not
* doing anything else but the protocol, this allows extra stuff
* to fit.
*/
ppi->is_new_state = 1;
delay_ms = pp_state_machine(ppi, NULL, 0);
while (1) {
int i;
again:
i = posix_net_check_pkt(ppi, delay_ms);
i = posix_net_check_pkt(ppg, delay_ms);
if (i < 0)
continue;
if (i == 0) {
delay_ms = pp_state_machine(ppi, NULL, 0);
delay_ms = run_all_state_machines(ppg);
continue;
}
/*
* We got a packet. If it's not ours, continue consuming
* the pending timeout
*/
i = ppi->n_ops->recv(ppi, ppi->rx_frame,
PP_MAX_FRAME_LENGTH - 4,
&ppi->last_rcv_time);
ppi->last_rcv_time.seconds += DSPRO(ppi)->currentUtcOffset;
if (i < PP_MINIMUM_LENGTH) {
pp_diag(ppi, frames, 1, "Error or short packet: %d < %d\n", i,
PP_MINIMUM_LENGTH
);
delay_ms = -1;
goto again;
}
/* If delay_ms is -1, the above posix_net_check_pkt will continue
* consuming the previous timeout (see its implementation).
* This ensures that every state machine is called at least once
* every delay_ms */
delay_ms = -1;
for (j = 0; j < ppg->nlinks; j++) {
ppi = &ppg->pp_instances[j];
delay_ms = pp_state_machine(ppi, ppi->rx_ptp,
i - NP(ppi)->ptp_offset);
if ((NP(ppi)->ch[PP_NP_GEN].pkt_present) ||
(NP(ppi)->ch[PP_NP_EVT].pkt_present)) {
/* We got some packets. If not ours, go on to the next ppi */
i = ppi->n_ops->recv(ppi, ppi->rx_frame,
PP_MAX_FRAME_LENGTH - 4,
&ppi->last_rcv_time);
ppi->last_rcv_time.seconds += DSPRO(ppi)->currentUtcOffset;
if (i < PP_MINIMUM_LENGTH) {
pp_diag(ppi, frames, 1, "Error or short packet: %d < %d\n", i,
PP_MINIMUM_LENGTH
);
continue;
}
pp_state_machine(ppi, ppi->rx_ptp,
i - NP(ppi)->ptp_offset);
}
}
}
}
......@@ -394,15 +394,13 @@ static int posix_net_exit(struct pp_instance *ppi)
return 0;
}
int posix_net_check_pkt(struct pp_instance *ppi, int delay_ms)
int posix_net_check_pkt(struct pp_globals *ppg, int delay_ms)
{
fd_set set;
int i;
int i, j;
int ret = 0;
int maxfd;
struct posix_arch_data *arch_data =
(struct posix_arch_data *)ppi->arch_data;
int maxfd = 0;
struct posix_arch_data *arch_data = POSIX_ARCH(ppg);
if (delay_ms != -1) {
/* Wait for a packet or for the timeout */
......@@ -410,35 +408,37 @@ int posix_net_check_pkt(struct pp_instance *ppi, int delay_ms)
arch_data->tv.tv_usec = (delay_ms % 1000) * 1000;
}
NP(ppi)->ch[PP_NP_GEN].pkt_present = 0;
NP(ppi)->ch[PP_NP_EVT].pkt_present = 0;
/* Detect general timeout with no needs for select stuff */
if ((arch_data->tv.tv_sec == 0) && (arch_data->tv.tv_usec == 0))
return 0;
if (ppi->ethernet_mode) {
maxfd = NP(ppi)->ch[PP_NP_GEN].fd;
FD_ZERO(&set);
FD_SET(NP(ppi)->ch[PP_NP_GEN].fd, &set);
FD_ZERO(&set);
i = select(maxfd + 1, &set, NULL, NULL, &arch_data->tv);
for (j = 0; j < ppg->nlinks; j++) {
struct pp_instance *ppi = &ppg->pp_instances[j];
int fd_to_set;
if (i < 0 && errno != EINTR)
exit(__LINE__);
NP(ppi)->ch[PP_NP_GEN].pkt_present = 0;
NP(ppi)->ch[PP_NP_EVT].pkt_present = 0;
if (i < 0)
return -1;
if (ppi->ethernet_mode) {
if (i == 0)
return 0;
fd_to_set = NP(ppi)->ch[PP_NP_GEN].fd;
FD_SET(fd_to_set, &set);
maxfd = fd_to_set > maxfd ? fd_to_set : maxfd;
continue;
}
/* else: UDP */
fd_to_set = NP(ppi)->ch[PP_NP_GEN].fd;
FD_SET(fd_to_set, &set);
maxfd = fd_to_set > maxfd ? fd_to_set : maxfd;
NP(ppi)->ch[PP_NP_GEN].pkt_present = 1;
return 1;
fd_to_set = NP(ppi)->ch[PP_NP_EVT].fd;
FD_SET(fd_to_set, &set);
maxfd = fd_to_set > maxfd ? fd_to_set : maxfd;
}
/* else: UDP */
maxfd = (NP(ppi)->ch[PP_NP_GEN].fd > NP(ppi)->ch[PP_NP_EVT].fd) ?
NP(ppi)->ch[PP_NP_GEN].fd : NP(ppi)->ch[PP_NP_EVT].fd;
FD_ZERO(&set);
FD_SET(NP(ppi)->ch[PP_NP_GEN].fd, &set);
FD_SET(NP(ppi)->ch[PP_NP_EVT].fd, &set);
i = select(maxfd + 1, &set, NULL, NULL, &arch_data->tv);
if (i < 0 && errno != EINTR)
......@@ -450,16 +450,19 @@ int posix_net_check_pkt(struct pp_instance *ppi, int delay_ms)
if (i == 0)
return 0;
if (FD_ISSET(NP(ppi)->ch[PP_NP_GEN].fd, &set)) {
ret++;
NP(ppi)->ch[PP_NP_GEN].pkt_present = 1;
}
for (j = 0; j < ppg->nlinks; j++) {
struct pp_instance *ppi = &ppg->pp_instances[j];
if (FD_ISSET(NP(ppi)->ch[PP_NP_EVT].fd, &set)) {
ret++;
NP(ppi)->ch[PP_NP_EVT].pkt_present = 1;
}
if (FD_ISSET(NP(ppi)->ch[PP_NP_GEN].fd, &set)) {
ret++;
NP(ppi)->ch[PP_NP_GEN].pkt_present = 1;
}
if (FD_ISSET(NP(ppi)->ch[PP_NP_EVT].fd, &set)) {
ret++;
NP(ppi)->ch[PP_NP_EVT].pkt_present = 1;
}
}
return ret;
}
......
......@@ -106,14 +106,14 @@ int main(int argc, char **argv)
ppi->portDS = calloc(1, sizeof(*ppi->portDS));
GLBS(ppi)->timePropertiesDS = calloc(1, sizeof(*GLBS(ppi)->timePropertiesDS));
GLBS(ppi)->servo = calloc(1, sizeof(*GLBS(ppi)->servo));
ppi->arch_data = calloc(1, sizeof(struct posix_arch_data));
ppg->arch_data = calloc(1, sizeof(struct posix_arch_data));
ppi->n_ops = &posix_net_ops;
ppi->t_ops = &posix_time_ops;
if ((!GLBS(ppi)->defaultDS) || (!GLBS(ppi)->currentDS) || (!GLBS(ppi)->parentDS)
|| (!ppi->portDS) || (!GLBS(ppi)->timePropertiesDS)
|| (!GLBS(ppi)->frgn_master) || (!ppi->arch_data)
|| (!GLBS(ppi)->frgn_master) || (!ppg->arch_data)
)
exit(__LINE__);
}
......
......@@ -11,7 +11,7 @@ struct posix_arch_data {
struct timeval tv;
};
extern int posix_net_check_pkt(struct pp_instance *ppi, int delay_ms);
extern int posix_net_check_pkt(struct pp_globals *ppg, int delay_ms);
extern void posix_main_loop(struct pp_globals *ppg);
......
......@@ -45,7 +45,7 @@ int ppsi_main(int argc, char **argv)
ppi->portDS = &portDS;
GLBS(ppi)->timePropertiesDS = &timePropertiesDS;
GLBS(ppi)->servo = &servo;
ppi->arch_data = NULL;
GLBS(ppi)->arch_data = NULL;
ppi->n_ops = &bare_net_ops;
ppi->t_ops = &bare_time_ops;
......
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