Commit 0c5b5e3a authored by Daniele Lacamera's avatar Daniele Lacamera

Added functions pico_icmpX_ping_abort to ICMP4 and ICMP6

API to cancel ongoing ping operation (Fix #167)
parent 1636ccee
......@@ -471,7 +471,7 @@ gateway_addr = pico_ip4 pico_ipv4_route_get_gateway(&dest_addr)
\end{verbatim}
\subsection{int$\_$pico$\_$icmp4$\_$ping}
\subsection{pico$\_$icmp4$\_$ping}
\subsubsection*{Description}
This function sends out a number of ping echo requests and checks if the replies are received correctly.
......@@ -515,7 +515,7 @@ With \textbf{err} values:
\end{itemize}
\subsubsection*{Return value}
On success, this call returns 0.
On success, this call returns a positive number, which is the ID of the ping operation just started.
On error, -1 is returned and \texttt{pico$\_$err} is set appropriately.
\subsubsection*{Errors}
......@@ -526,7 +526,36 @@ On error, -1 is returned and \texttt{pico$\_$err} is set appropriately.
\subsubsection*{Example}
\begin{verbatim}
ret = pico_icmp4_ping(dst_addr, 30, 10, 100, 1000, callback);
id = pico_icmp4_ping(dst_addr, 30, 10, 100, 1000, callback);
\end{verbatim}
\subsection{pico$\_$icmp4$\_$ping$\_$abort}
\subsubsection*{Description}
This function aborts an ongoing ping operation that has previously started using pico$\_$icmp4$\_$ping().
\subsubsection*{Function prototype}
\begin{verbatim}
int pico_icmp4_ping_abort(int id);
\end{verbatim}
\subsubsection*{Parameters}
\begin{itemize}[noitemsep]
\item \texttt{id} - identification number for the ping operation. This has been returned by \texttt{pico$\_$icmp4$\_$ping()} and it is intended to distinguish the operation to be cancelled.
\end{itemize}
\subsubsection*{Return value}
On success, this call returns 0.
On error, -1 is returned and \texttt{pico$\_$err} is set appropriately.
\subsubsection*{Errors}
\begin{itemize}[noitemsep]
\item \texttt{PICO$\_$ERR$\_$EINVAL} - invalid argument
\end{itemize}
\subsubsection*{Example}
\begin{verbatim}
ret = pico_icmp4_ping_abort(id);
\end{verbatim}
......@@ -176,7 +176,6 @@ struct pico_icmp4_ping_cookie
int interval;
int timeout;
void (*cb)(struct pico_icmp4_stats*);
};
static int cookie_compare(void *ka, void *kb)
......@@ -255,6 +254,9 @@ static void next_ping(pico_time now, void *arg)
IGNORE_PARAMETER(now);
if(pico_tree_findKey(&Pings, cookie)) {
if (cookie->err == PICO_PING_ERR_ABORTED)
return;
if (cookie->seq < (uint16_t)cookie->count) {
newcookie = PICO_ZALLOC(sizeof(struct pico_icmp4_ping_cookie));
if (!newcookie)
......@@ -280,6 +282,8 @@ static void ping_recv_reply(struct pico_frame *f)
cookie = pico_tree_findKey(&Pings, &test);
if (cookie) {
struct pico_icmp4_stats stats;
if (cookie->err == PICO_PING_ERR_ABORTED)
return;
cookie->err = PICO_PING_ERR_REPLIED;
stats.dst = ((struct pico_ipv4_hdr *)f->net_hdr)->src;
stats.seq = cookie->seq;
......@@ -328,8 +332,27 @@ int pico_icmp4_ping(char *dst, int count, int interval, int timeout, int size, v
pico_tree_insert(&Pings, cookie);
send_ping(cookie);
return 0;
return cookie->id;
}
int pico_icmp4_ping_abort(int id)
{
struct pico_tree_node *node;
int found = 0;
pico_tree_foreach(node, &Pings)
{
struct pico_icmp4_ping_cookie *ck =
(struct pico_icmp4_ping_cookie *) node->keyValue;
if (ck->id == id) {
ck->err = PICO_PING_ERR_ABORTED;
found++;
}
}
if (found > 0)
return 0; /* OK if at least one pending ping has been canceled */
pico_err = PICO_ERR_ENOENT;
return -1;
}
#endif
......@@ -141,9 +141,11 @@ int pico_icmp4_ttl_expired(struct pico_frame *f);
int pico_icmp4_packet_filtered(struct pico_frame *f);
int pico_icmp4_ping(char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp4_stats *));
int pico_icmp4_ping_abort(int id);
#define PICO_PING_ERR_REPLIED 0
#define PICO_PING_ERR_TIMEOUT 1
#define PICO_PING_ERR_UNREACH 2
#define PICO_PING_ERR_ABORTED 3
#define PICO_PING_ERR_PENDING 0xFFFF
#endif
......@@ -443,6 +443,8 @@ static void pico_icmp6_next_ping(pico_time now, void *arg)
cookie = (struct pico_icmp6_ping_cookie *)arg;
if (pico_tree_findKey(&IPV6Pings, cookie)) {
if (cookie->err == PICO_PING6_ERR_ABORTED)
return;
if (cookie->seq < (uint16_t)cookie->count) {
new = PICO_ZALLOC(sizeof(struct pico_icmp6_ping_cookie));
if (!new) {
......@@ -474,6 +476,8 @@ static void pico_icmp6_ping_recv_reply(struct pico_frame *f)
struct pico_icmp6_stats stats = {
0
};
if (cookie->err == PICO_PING6_ERR_ABORTED)
return;
cookie->err = PICO_PING6_ERR_REPLIED;
stats.dst = cookie->dst;
stats.seq = cookie->seq;
......@@ -521,7 +525,26 @@ int pico_icmp6_ping(char *dst, int count, int interval, int timeout, int size, v
pico_tree_insert(&IPV6Pings, cookie);
pico_icmp6_send_ping(cookie);
return 0;
return (int)cookie->id;
}
int pico_icmp6_ping_abort(int id)
{
struct pico_tree_node *node;
int found = 0;
pico_tree_foreach(node, &IPV6Pings)
{
struct pico_icmp6_ping_cookie *ck =
(struct pico_icmp6_ping_cookie *) node->keyValue;
if (ck->id == (uint16_t)id) {
ck->err = PICO_PING6_ERR_ABORTED;
found++;
}
}
if (found > 0)
return 0; /* OK if at least one pending ping has been canceled */
pico_err = PICO_ERR_ENOENT;
return -1;
}
#endif
......@@ -56,6 +56,7 @@
#define PICO_PING6_ERR_REPLIED 0
#define PICO_PING6_ERR_TIMEOUT 1
#define PICO_PING6_ERR_UNREACH 2
#define PICO_PING6_ERR_ABORTED 3
#define PICO_PING6_ERR_PENDING 0xFFFF
/* custom defines */
......@@ -198,6 +199,7 @@ struct pico_icmp6_stats
};
int pico_icmp6_ping(char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp6_stats *));
int pico_icmp6_ping_abort(int id);
int pico_icmp6_neighbor_solicitation(struct pico_device *dev, struct pico_ip6 *dst, uint8_t type);
int pico_icmp6_neighbor_advertisement(struct pico_frame *f, struct pico_ip6 *target);
......
......@@ -10,13 +10,18 @@ killall picoapp6.elf
echo "IPV6 tests!"
echo "PING6 LOCALHOST"
./build/test/picoapp6.elf --loop -a ping,::1, || exit 1
./build/test/picoapp6.elf --loop -a ping,::1,, || exit 1
echo "PING6 TEST"
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::1,ffff::,,,,) &
./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::2,ffff::,,, -a ping,aaaa::1, || exit 1
./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::2,ffff::,,, -a ping,aaaa::1,, || exit 1
killall picoapp6.elf
echo "PING6 TEST (aborted in 4 seconds...)"
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::1,ffff::,,,,) &
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::2,ffff::,,, -a ping,aaaa::1,4,) &
sleep 7
killall picoapp6.elf
echo "TCP6 TEST"
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::1,ffff::,,, -a tcpbench,r,6667,,) &
......@@ -61,7 +66,13 @@ echo "PING LOCALHOST"
echo "PING TEST"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0:::) &
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a ping:10.40.0.8: || exit 1
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a ping:10.40.0.8:: || exit 1
killall picoapp.elf
echo "PING TEST -- Aborted in 4 seconds"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0:::) &
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a ping:10.40.0.8:4:) &
sleep 7
killall picoapp.elf
echo "TCP TEST"
......
......@@ -1769,22 +1769,54 @@ void cb_ping6(struct pico_icmp6_stats *s)
}
#endif
void ping_abort_timer(pico_time now, void *_id)
{
int *id = (int *) _id;
printf("Ping: aborting...\n");
if (!IPV6_MODE)
pico_icmp4_ping_abort(*id);
#ifdef PICO_SUPPORT_IPV6
else
pico_icmp6_ping_abort(*id);
#endif
}
void app_ping(char *arg)
{
char *dest = NULL;
cpy_arg(&dest, arg);
char *next, *abort;
static int id;
int timeout = 0;
next = cpy_arg(&dest, arg);
if (!dest) {
fprintf(stderr, "ping needs the following format: ping:dst_addr\n");
fprintf(stderr, "ping needs the following format: ping:dst_addr:[abort after N sec]\n");
exit(255);
}
if (next) {
next = cpy_arg(&abort, next);
if (strlen(abort) > 0) {
printf("Got arg: '%s'\n", abort);
timeout = atoi(abort);
if (timeout <= 0) {
fprintf(stderr, "ping needs the following format: ping:dst_addr:[abort after N sec]\n");
exit(255);
}
printf("Aborting ping after %d seconds\n", timeout);
}
}
if (!IPV6_MODE)
pico_icmp4_ping(dest, NUM_PING, 1000, 10000, 64, cb_ping);
id = pico_icmp4_ping(dest, NUM_PING, 1000, 10000, 64, cb_ping);
#ifdef PICO_SUPPORT_IPV6
else
pico_icmp6_ping(dest, NUM_PING, 1000, 10000, 64, cb_ping6);
id = pico_icmp6_ping(dest, NUM_PING, 1000, 10000, 64, cb_ping6);
#endif
if (timeout > 0) {
printf("Adding abort timer after %d seconds for id %d\n", timeout, id);
pico_timer_add(timeout * 1000, ping_abort_timer, &id);
}
}
#endif
/*** END PING ***/
......
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