Acked-by: Donald Sharp <[email protected]> On Tue, Nov 10, 2015 at 12:33 PM, Christian Franke < [email protected]> wrote:
> Signed-off-by: Christian Franke <[email protected]> > --- > isisd/isis_bpf.c | 11 ++++-- > isisd/isis_dlpi.c | 30 ++++++++++++++--- > isisd/isis_pdu.c | 92 > ++++++++++++++++++++++++++++++++------------------- > isisd/isis_pfpacket.c | 29 ++++++++++++---- > 4 files changed, 114 insertions(+), 48 deletions(-) > > diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c > index f6176ef..f6d7915 100644 > --- a/isisd/isis_bpf.c > +++ b/isisd/isis_bpf.c > @@ -29,6 +29,7 @@ > #include <net/bpf.h> > > #include "log.h" > +#include "network.h" > #include "stream.h" > #include "if.h" > > @@ -339,8 +340,14 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, > int level) > > /* now we can send this */ > written = write (circuit->fd, sock_buff, buflen); > - > - return ISIS_OK; > + if (rv < 0) > + { > + zlog_warn("IS-IS bpf: could not transmit packet on %s: %s", > + circuit->interface->name, safe_strerror(errno)); > + if (ERRNO_IO_RETRY(errno)) > + return ISIS_WARNING; > + return ISIS_ERROR; > + } > } > > int > diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c > index b583d10..7c7e090 100644 > --- a/isisd/isis_dlpi.c > +++ b/isisd/isis_dlpi.c > @@ -33,6 +33,7 @@ > #include <sys/pfmod.h> > > #include "log.h" > +#include "network.h" > #include "stream.h" > #include "if.h" > > @@ -90,13 +91,14 @@ static u_short pf_filter[] = > * interfaces plus the (optional; not needed) Solaris packet filter > module. > */ > > -static void > +static int > dlpisend (int fd, const void *cbuf, size_t cbuflen, > const void *dbuf, size_t dbuflen, int flags) > { > const struct strbuf *ctlptr = NULL; > const struct strbuf *dataptr = NULL; > struct strbuf ctlbuf, databuf; > + int rv; > > if (cbuf != NULL) > { > @@ -115,8 +117,16 @@ dlpisend (int fd, const void *cbuf, size_t cbuflen, > } > > /* We assume this doesn't happen often and isn't operationally > significant */ > - if (putmsg (fd, ctlptr, dataptr, flags) == -1) > - zlog_debug ("%s: putmsg: %s", __func__, safe_strerror (errno)); > + rv = putmsg(fd, ctlptr, dataptr, flags); > + if (rv == -1 && dbuf == NULL) > + { > + /* > + * For actual PDU transmission - recognizable buf dbuf != NULL, > + * the error is passed upwards and should not be printed here. > + */ > + zlog_debug ("%s: putmsg: %s", __func__, safe_strerror (errno)); > + } > + return rv; > } > > static ssize_t > @@ -587,6 +597,7 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int > level) > char *dstaddr; > u_short *dstsap; > int buflen; > + int rv; > > buflen = stream_get_endp (circuit->snd_stream) + LLC_LEN; > if ((size_t)buflen > sizeof (sock_buff)) > @@ -626,8 +637,17 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, > int level) > sock_buff[2] = 0x03; > memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data, > stream_get_endp (circuit->snd_stream)); > - dlpisend (circuit->fd, dur, sizeof (*dur) + dur->dl_dest_addr_length, > - sock_buff, buflen, 0); > + rv = dlpisend(circuit->fd, dur, sizeof (*dur) + > dur->dl_dest_addr_length, > + sock_buff, buflen, 0); > + if (rv < 0) > + { > + zlog_warn("IS-IS dlpi: could not transmit packet on %s: %s", > + circuit->interface->name, safe_strerror(errno)); > + if (ERRNO_IO_RETRY(errno)) > + return ISIS_WARNING; > + return ISIS_ERROR; > + } > + > return ISIS_OK; > } > > diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c > index 4c420f3..0401e44 100644 > --- a/isisd/isis_pdu.c > +++ b/isisd/isis_pdu.c > @@ -3087,15 +3087,14 @@ send_lsp (struct thread *thread) > struct isis_circuit *circuit; > struct isis_lsp *lsp; > struct listnode *node; > + int clear_srm = 1; > int retval = ISIS_OK; > > circuit = THREAD_ARG (thread); > assert (circuit); > > - if (circuit->state != C_STATE_UP || circuit->is_passive == 1) > - { > - return retval; > - } > + if (!circuit->lsp_queue) > + return ISIS_OK; > > node = listhead (circuit->lsp_queue); > > @@ -3105,28 +3104,56 @@ send_lsp (struct thread *thread) > * thread gets a chance to run. > */ > if (!node) > - { > - return retval; > - } > + return ISIS_OK; > > + /* > + * Delete LSP from lsp_queue. If it's still in queue, it is assumed > + * as 'transmit pending', but send_lsp may never be called again. > + * Retry will happen because SRM flag will not be cleared. > + */ > lsp = listgetdata(node); > + list_delete_node (circuit->lsp_queue, node); > + > + /* Set the last-cleared time if the queue is empty. */ > + /* TODO: Is is possible that new lsps keep being added to the queue > + * that the queue is never empty? */ > + if (list_isempty (circuit->lsp_queue)) > + circuit->lsp_queue_last_cleared = time (NULL); > + > + if (circuit->state != C_STATE_UP || circuit->is_passive == 1) > + goto out; > > /* > * Do not send if levels do not match > */ > if (!(lsp->level & circuit->is_type)) > - { > - list_delete_node (circuit->lsp_queue, node); > - return retval; > - } > + goto out; > > /* > * Do not send if we do not have adjacencies in state up on the circuit > */ > if (circuit->upadjcount[lsp->level - 1] == 0) > - { > - list_delete_node (circuit->lsp_queue, node); > - return retval; > + goto out; > + > + /* stream_copy will assert and stop program execution if LSP is larger > than > + * the circuit's MTU. So handle and log this case here. */ > + if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream)) > + { > + zlog_err("ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x," > + " cksum 0x%04x, lifetime %us on %s. LSP Size is %zu" > + " while interface stream size is %zu.", > + circuit->area->area_tag, lsp->level, > + rawlspid_print(lsp->lsp_header->lsp_id), > + ntohl(lsp->lsp_header->seq_num), > + ntohs(lsp->lsp_header->checksum), > + ntohs(lsp->lsp_header->rem_lifetime), > + circuit->interface->name, > + stream_get_endp(lsp->pdu), > + stream_get_size(circuit->snd_stream)); > + if (isis->debugs & DEBUG_PACKET_DUMP) > + zlog_dump_data(STREAM_DATA(lsp->pdu), stream_get_endp(lsp->pdu)); > + retval = ISIS_ERROR; > + goto out; > } > > /* copy our lsp to the send buffer */ > @@ -3147,32 +3174,29 @@ send_lsp (struct thread *thread) > stream_get_endp (circuit->snd_stream)); > } > > + clear_srm = 0; > retval = circuit->tx (circuit, lsp->level); > if (retval != ISIS_OK) > { > - zlog_err ("ISIS-Upd (%s): Send L%d LSP on %s failed", > + zlog_err ("ISIS-Upd (%s): Send L%d LSP on %s failed %s", > circuit->area->area_tag, lsp->level, > - circuit->interface->name); > - return retval; > + circuit->interface->name, > + (retval == ISIS_WARNING) ? "temporarily" : "permanently"); > } > > - /* > - * If the sending succeeded, we can del the lsp from circuits > - * lsp_queue > - */ > - list_delete_node (circuit->lsp_queue, node); > - > - /* Set the last-cleared time if the queue is empty. */ > - /* TODO: Is is possible that new lsps keep being added to the queue > - * that the queue is never empty? */ > - if (list_isempty (circuit->lsp_queue)) > - circuit->lsp_queue_last_cleared = time (NULL); > - > - /* > - * On broadcast circuits also the SRMflag can be cleared > - */ > - if (circuit->circ_type == CIRCUIT_T_BROADCAST) > - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); > +out: > + if (clear_srm > + || (retval == ISIS_OK && circuit->circ_type == CIRCUIT_T_BROADCAST) > + || (retval != ISIS_OK && retval != ISIS_WARNING)) > + { > + /* SRM flag will trigger retransmission. We will not retransmit if > we > + * encountered a fatal error. > + * On success, they should only be cleared if it's a broadcast > circuit. > + * On a P2P circuit, we will wait for the ack from the neighbor to > clear > + * the fag. > + */ > + ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); > + } > > return retval; > } > diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c > index a9ecd40..2427047 100644 > --- a/isisd/isis_pfpacket.c > +++ b/isisd/isis_pfpacket.c > @@ -26,6 +26,7 @@ > #include <netpacket/packet.h> > > #include "log.h" > +#include "network.h" > #include "stream.h" > #include "if.h" > > @@ -367,8 +368,14 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, > int level) > iov[1].iov_base = circuit->snd_stream->data; > iov[1].iov_len = stream_get_endp (circuit->snd_stream); > > - sendmsg (circuit->fd, &msg, 0); > - > + if (sendmsg(circuit->fd, &msg, 0) < 0) > + { > + zlog_warn("IS-IS pfpacket: could not transmit packet on %s: %s", > + circuit->interface->name, safe_strerror(errno)); > + if (ERRNO_IO_RETRY(errno)) > + return ISIS_WARNING; > + return ISIS_ERROR; > + } > return ISIS_OK; > } > > @@ -376,6 +383,7 @@ int > isis_send_pdu_p2p (struct isis_circuit *circuit, int level) > { > struct sockaddr_ll sa; > + ssize_t rv; > > stream_set_getp (circuit->snd_stream, 0); > memset (&sa, 0, sizeof (struct sockaddr_ll)); > @@ -391,11 +399,18 @@ isis_send_pdu_p2p (struct isis_circuit *circuit, int > level) > > /* lets try correcting the protocol */ > sa.sll_protocol = htons (0x00FE); > - sendto (circuit->fd, circuit->snd_stream->data, > - stream_get_endp (circuit->snd_stream), 0, > - (struct sockaddr *) &sa, > - sizeof (struct sockaddr_ll)); > - > + rv = sendto(circuit->fd, circuit->snd_stream->data, > + stream_get_endp (circuit->snd_stream), 0, > + (struct sockaddr *) &sa, > + sizeof (struct sockaddr_ll)); > + if (rv < 0) > + { > + zlog_warn("IS-IS pfpacket: could not transmit packet on %s: %s", > + circuit->interface->name, safe_strerror(errno)); > + if (ERRNO_IO_RETRY(errno)) > + return ISIS_WARNING; > + return ISIS_ERROR; > + } > return ISIS_OK; > } > > -- > 2.6.1 > > > _______________________________________________ > Quagga-dev mailing list > [email protected] > https://lists.quagga.net/mailman/listinfo/quagga-dev >
_______________________________________________ Quagga-dev mailing list [email protected] https://lists.quagga.net/mailman/listinfo/quagga-dev
