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

Reply via email to