]> git.puffer.fish Git - matthieu/frr.git/commitdiff
isisd: allow to adjust lsp-mtu
authorChristian Franke <nobody@nowhere.ws>
Tue, 10 Nov 2015 17:43:31 +0000 (18:43 +0100)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 30 Mar 2016 00:26:20 +0000 (20:26 -0400)
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
isisd/isis_circuit.c
isisd/isis_circuit.h
isisd/isis_constants.h
isisd/isis_lsp.c
isisd/isis_lsp.h
isisd/isis_pdu.c
isisd/isisd.c
isisd/isisd.h

index 9f597368d47ccf136f67a003390dc4f7111c5f59..a49994a78bb908c2dde302ede8cb9d7ce6ac47c0 100644 (file)
@@ -574,6 +574,29 @@ isis_circuit_update_all_srmflags (struct isis_circuit *circuit, int is_set)
     }
 }
 
+size_t
+isis_circuit_pdu_size(struct isis_circuit *circuit)
+{
+  return ISO_MTU(circuit);
+}
+
+void
+isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream)
+{
+  size_t stream_size = isis_circuit_pdu_size(circuit);
+
+  if (!*stream)
+    {
+      *stream = stream_new(stream_size);
+    }
+  else
+    {
+      if (STREAM_SIZE(*stream) != stream_size)
+        stream_resize(*stream, stream_size);
+      stream_reset(*stream);
+    }
+}
+
 int
 isis_circuit_up (struct isis_circuit *circuit)
 {
@@ -588,6 +611,15 @@ isis_circuit_up (struct isis_circuit *circuit)
   if (circuit->is_passive)
     return ISIS_OK;
 
+  if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit))
+    {
+      zlog_err("Interface MTU %zu on %s is too low to support area lsp mtu %u!",
+               isis_circuit_pdu_size(circuit), circuit->interface->name,
+               circuit->area->lsp_mtu);
+      isis_circuit_down(circuit);
+      return ISIS_ERROR;
+    }
+
   if (circuit->circ_type == CIRCUIT_T_BROADCAST)
     {
       /*
@@ -620,9 +652,6 @@ isis_circuit_up (struct isis_circuit *circuit)
       circuit->u.bc.adjdb[0] = list_new ();
       circuit->u.bc.adjdb[1] = list_new ();
 
-      if (circuit->area->min_bcast_mtu == 0 ||
-          ISO_MTU (circuit) < circuit->area->min_bcast_mtu)
-        circuit->area->min_bcast_mtu = ISO_MTU (circuit);
       /*
        * ISO 10589 - 8.4.1 Enabling of broadcast circuits
        */
@@ -684,11 +713,8 @@ isis_circuit_up (struct isis_circuit *circuit)
     }
 
   /* initialize the circuit streams after opening connection */
-  if (circuit->rcv_stream == NULL)
-    circuit->rcv_stream = stream_new (ISO_MTU (circuit));
-
-  if (circuit->snd_stream == NULL)
-    circuit->snd_stream = stream_new (ISO_MTU (circuit));
+  isis_circuit_stream(circuit, &circuit->rcv_stream);
+  isis_circuit_stream(circuit, &circuit->snd_stream);
 
 #ifdef GNU_LINUX
   THREAD_READ_ON (master, circuit->t_read, isis_receive, circuit,
@@ -1192,6 +1218,7 @@ DEFUN (ip_router_isis,
   struct isis_circuit *circuit;
   struct interface *ifp;
   struct isis_area *area;
+  int rv;
 
   ifp = (struct interface *) vty->index;
   assert (ifp);
@@ -1220,16 +1247,25 @@ DEFUN (ip_router_isis,
   area = vty->index;
 
   circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area);
-  isis_circuit_if_bind (circuit, ifp);
+  if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP)
+    {
+      vty_out(vty, "Couldn't bring up interface, please check log.%s", VTY_NEWLINE);
+      rv = CMD_WARNING;
+    }
+  else
+    {
+      isis_circuit_if_bind (circuit, ifp);
 
-  circuit->ip_router = 1;
-  area->ip_circuits++;
-  circuit_update_nlpids (circuit);
+      circuit->ip_router = 1;
+      area->ip_circuits++;
+      circuit_update_nlpids (circuit);
+      rv = CMD_SUCCESS;
+    }
 
   vty->node = INTERFACE_NODE;
   vty->index = ifp;
 
-  return CMD_SUCCESS;
+  return rv;
 }
 
 DEFUN (no_ip_router_isis,
@@ -1290,6 +1326,7 @@ DEFUN (ipv6_router_isis,
   struct isis_circuit *circuit;
   struct interface *ifp;
   struct isis_area *area;
+  int rv;
 
   ifp = (struct interface *) vty->index;
   assert (ifp);
@@ -1318,16 +1355,25 @@ DEFUN (ipv6_router_isis,
   area = vty->index;
 
   circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area);
-  isis_circuit_if_bind (circuit, ifp);
+  if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP)
+    {
+      vty_out(vty, "Couldn't bring up interface, please check log.%s", VTY_NEWLINE);
+      rv = CMD_WARNING;
+    }
+  else
+    {
+      isis_circuit_if_bind (circuit, ifp);
 
-  circuit->ipv6_router = 1;
-  area->ipv6_circuits++;
-  circuit_update_nlpids (circuit);
+      circuit->ipv6_router = 1;
+      area->ipv6_circuits++;
+      circuit_update_nlpids (circuit);
+      rv = CMD_SUCCESS;
+    }
 
   vty->node = INTERFACE_NODE;
   vty->index = ifp;
 
-  return CMD_SUCCESS;
+  return rv;
 }
 
 DEFUN (no_ipv6_router_isis,
index d86fee040eb6b40a5c467fcf26bd9e039217de20..d883879731e1a42b2316083ed8dbbc94809b5b77 100644 (file)
@@ -164,5 +164,7 @@ void isis_circuit_down (struct isis_circuit *);
 void circuit_update_nlpids (struct isis_circuit *circuit);
 void isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty,
                              char detail);
+size_t isis_circuit_pdu_size(struct isis_circuit *circuit);
+void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream);
 
 #endif /* _ZEBRA_ISIS_CIRCUIT_H */
index bb2c4b40610da3f65fbf64802e01d610fabb5bdf..8b21894e433b16d9c2ee3fca5ec35797b66111ba 100644 (file)
@@ -34,7 +34,6 @@
 #define ISO_SAP                       0xFE
 #define INTRADOMAIN_ROUTEING_SELECTOR 0
 #define SEQUENCE_MODULUS              4294967296
-#define RECEIVE_LSP_BUFFER_SIZE       1492
 
 /*
  * implementation specific jitter values
index 452a8a678f7073fd2064d501f13a5d739b29467a..ed4ce25637306dbb922b577727290a645f08b91e 100644 (file)
@@ -575,15 +575,16 @@ lsp_new_from_stream_ptr (struct stream *stream,
 }
 
 struct isis_lsp *
-lsp_new (u_char * lsp_id, u_int16_t rem_lifetime, u_int32_t seq_num,
-        u_int8_t lsp_bits, u_int16_t checksum, int level)
+lsp_new(struct isis_area *area, u_char * lsp_id,
+       u_int16_t rem_lifetime, u_int32_t seq_num,
+       u_int8_t lsp_bits, u_int16_t checksum, int level)
 {
   struct isis_lsp *lsp;
 
   lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
+  lsp->area = area;
 
-  /* FIXME: Should be minimal mtu? */
-  lsp->pdu = stream_new (1500);
+  lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
   if (LSP_FRAGMENT (lsp_id) == 0)
     lsp->lspu.frags = list_new ();
   lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu));
@@ -1131,7 +1132,7 @@ lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area,
       lsp_clear_data (lsp);
       return lsp;
     }
-  lsp = lsp_new (frag_id, ntohs(lsp0->lsp_header->rem_lifetime), 0,
+  lsp = lsp_new (area, frag_id, ntohs(lsp0->lsp_header->rem_lifetime), 0,
                  lsp_bits_generate (level, area->overload_bit,
                  area->attached_bit), 0, level);
   lsp->area = area;
@@ -1593,7 +1594,7 @@ lsp_generate (struct isis_area *area, int level)
                               area->lspdb[level - 1]);
     }
   rem_lifetime = lsp_rem_lifetime (area, level);
-  newlsp = lsp_new (lspid, rem_lifetime, seq_num,
+  newlsp = lsp_new (area, lspid, rem_lifetime, seq_num,
                     area->is_type | area->overload_bit | area->attached_bit,
                     0, level);
   newlsp->area = area;
@@ -1966,7 +1967,7 @@ lsp_generate_pseudo (struct isis_circuit *circuit, int level)
 
   rem_lifetime = lsp_rem_lifetime (circuit->area, level);
   /* RFC3787  section 4 SHOULD not set overload bit in pseudo LSPs */
-  lsp = lsp_new (lsp_id, rem_lifetime, 1,
+  lsp = lsp_new (circuit->area, lsp_id, rem_lifetime, 1,
                  circuit->area->is_type | circuit->area->attached_bit,
                  0, level);
   lsp->area = circuit->area;
@@ -2356,8 +2357,7 @@ lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
   lsp->area = area;
   lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ?
     IS_LEVEL_1 : IS_LEVEL_2;
-  /* FIXME: Should be minimal mtu? */
-  lsp->pdu = stream_new (1500);
+  lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
   lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu);
   fill_fixed_hdr (lsp->isis_header, (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE
                  : L2_LINK_STATE);
@@ -2479,11 +2479,11 @@ generate_topology_lsps (struct isis_area *area)
       lspid[ISIS_SYS_ID_LEN - 2] = ((i >> 8) & 0xFF);
 
       rem_lifetime = lsp_rem_lifetime (area, IS_LEVEL_1);
-      lsp = lsp_new (lspid, rem_lifetime, 1, IS_LEVEL_1 | area->overload_bit
-                     | area->attached_bit, 0, 1);
+      lsp = lsp_new (area, lspid, rem_lifetime, 1,
+                     IS_LEVEL_1 | area->overload_bit | area->attached_bit,
+                     0, 1);
       if (!lsp)
        return;
-      lsp->area = area;
       lsp->from_topology = 1;
 
       /* Creating LSP data based on topology info. */
index 6e7f745d2a3e2dbdde7a59c5e7022bb1f33aa06c..92a5dfe595274e9051da81c9b32f2df82393676e 100644 (file)
@@ -66,7 +66,8 @@ int lsp_regenerate_schedule (struct isis_area *area, int level,
 int lsp_generate_pseudo (struct isis_circuit *circuit, int level);
 int lsp_regenerate_schedule_pseudo (struct isis_circuit *circuit, int level);
 
-struct isis_lsp *lsp_new (u_char * lsp_id, u_int16_t rem_lifetime,
+struct isis_lsp *lsp_new (struct isis_area *area, u_char * lsp_id,
+                         u_int16_t rem_lifetime,
                          u_int32_t seq_num, u_int8_t lsp_bits,
                          u_int16_t checksum, int level);
 struct isis_lsp *lsp_new_from_stream_ptr (struct stream *stream,
index d9e98f268365e688fc233f43b2cc3d5755f45efa..361a90be85d321d8e71ab0862393dbca3c5138ee 100644 (file)
@@ -1867,9 +1867,9 @@ process_snp (int snp_type, int level, struct isis_circuit *circuit,
            if (entry->rem_lifetime && entry->checksum && entry->seq_num &&
                memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN))
              {
-               lsp = lsp_new (entry->lsp_id, ntohs (entry->rem_lifetime),
-                              0, 0, entry->checksum, level);
-               lsp->area = circuit->area;
+               lsp = lsp_new(circuit->area, entry->lsp_id,
+                             ntohs(entry->rem_lifetime),
+                             0, 0, entry->checksum, level);
                lsp_insert (lsp, circuit->area->lspdb[level - 1]);
                ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags);
                ISIS_SET_FLAG (lsp->SSNflags, circuit);
@@ -2093,10 +2093,7 @@ isis_receive (struct thread *thread)
   circuit = THREAD_ARG (thread);
   assert (circuit);
 
-  if (circuit->rcv_stream == NULL)
-    circuit->rcv_stream = stream_new (ISO_MTU (circuit));
-  else
-    stream_reset (circuit->rcv_stream);
+  isis_circuit_stream(circuit, &circuit->rcv_stream);
 
   retval = circuit->rx (circuit, ssnpa);
   circuit->t_read = NULL;
@@ -2132,10 +2129,7 @@ isis_receive (struct thread *thread)
 
   circuit->t_read = NULL;
 
-  if (circuit->rcv_stream == NULL)
-    circuit->rcv_stream = stream_new (ISO_MTU (circuit));
-  else
-    stream_reset (circuit->rcv_stream);
+  isis_circuit_stream(circuit, &circuit->rcv_stream);
 
   retval = circuit->rx (circuit, ssnpa);
 
@@ -2240,10 +2234,7 @@ send_hello (struct isis_circuit *circuit, int level)
       return ISIS_WARNING;
     }
 
-  if (!circuit->snd_stream)
-    circuit->snd_stream = stream_new (ISO_MTU (circuit));
-  else
-    stream_reset (circuit->snd_stream);
+  isis_circuit_stream(circuit, &circuit->snd_stream);
 
   if (circuit->circ_type == CIRCUIT_T_BROADCAST)
     if (level == IS_LEVEL_1)
@@ -2501,10 +2492,7 @@ build_csnp (int level, u_char * start, u_char * stop, struct list *lsps,
   unsigned long auth_tlv_offset = 0;
   int retval = ISIS_OK;
 
-  if (circuit->snd_stream == NULL)
-    circuit->snd_stream = stream_new (ISO_MTU (circuit));
-  else
-    stream_reset (circuit->snd_stream);
+  isis_circuit_stream(circuit, &circuit->snd_stream);
 
   if (level == IS_LEVEL_1)
     fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM,
@@ -2828,10 +2816,7 @@ build_psnp (int level, struct isis_circuit *circuit, struct list *lsps)
   unsigned long auth_tlv_offset = 0;
   int retval = ISIS_OK;
 
-  if (circuit->snd_stream == NULL)
-    circuit->snd_stream = stream_new (ISO_MTU (circuit));
-  else
-    stream_reset (circuit->snd_stream);
+  isis_circuit_stream(circuit, &circuit->snd_stream);
 
   if (level == IS_LEVEL_1)
     fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM,
@@ -3153,10 +3138,7 @@ ack_lsp (struct isis_link_state_hdr *hdr, struct isis_circuit *circuit,
   u_int16_t length;
   struct isis_fixed_hdr fixed_hdr;
 
-  if (!circuit->snd_stream)
-    circuit->snd_stream = stream_new (ISO_MTU (circuit));
-  else
-    stream_reset (circuit->snd_stream);
+  isis_circuit_stream(circuit, &circuit->snd_stream);
 
   //  fill_llc_hdr (stream);
   if (level == IS_LEVEL_1)
index d786f402a04e5c9416fcfdbd1cba10b6529b0c0b..ee47f36a8398669f8c35aa1de4710404bedb2363 100644 (file)
@@ -158,13 +158,11 @@ isis_area_create (const char *area_tag)
   area->oldmetric = 0;
   area->newmetric = 1;
   area->lsp_frag_threshold = 90;
+  area->lsp_mtu = DEFAULT_LSP_MTU;
 #ifdef TOPOLOGY_GENERATE
   memcpy (area->topology_baseis, DEFAULT_TOPOLOGY_BASEIS, ISIS_SYS_ID_LEN);
 #endif /* TOPOLOGY_GENERATE */
 
-  /* FIXME: Think of a better way... */
-  area->min_bcast_mtu = 1497;
-
   area->area_tag = strdup (area_tag);
   listnode_add (isis->area_list, area);
   area->isis = isis;
@@ -1546,6 +1544,76 @@ DEFUN (no_net,
   return area_clear_net_title (vty, argv[0]);
 }
 
+static
+int area_set_lsp_mtu(struct vty *vty, struct isis_area *area, unsigned int lsp_mtu)
+{
+  struct isis_circuit *circuit;
+  struct listnode *node;
+
+  for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
+    {
+      if(lsp_mtu > isis_circuit_pdu_size(circuit))
+        {
+          vty_out(vty, "ISIS area contains circuit %s, which has a maximum PDU size of %zu.%s",
+                  circuit->interface->name, isis_circuit_pdu_size(circuit),
+                  VTY_NEWLINE);
+          return CMD_ERR_AMBIGUOUS;
+        }
+    }
+
+  area->lsp_mtu = lsp_mtu;
+  lsp_regenerate_schedule(area, IS_LEVEL_1_AND_2, 1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (area_lsp_mtu,
+       area_lsp_mtu_cmd,
+       "lsp-mtu <128-4352>",
+       "Configure the maximum size of generated LSPs\n"
+       "Maximum size of generated LSPs\n")
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  if (!area)
+    {
+      vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+      return CMD_ERR_NO_MATCH;
+    }
+
+  unsigned int lsp_mtu;
+
+  VTY_GET_INTEGER_RANGE("lsp-mtu", lsp_mtu, argv[0], 128, 4352);
+
+  return area_set_lsp_mtu(vty, area, lsp_mtu);
+}
+
+DEFUN(no_area_lsp_mtu,
+      no_area_lsp_mtu_cmd,
+      "no lsp-mtu",
+      NO_STR
+      "Configure the maximum size of generated LSPs\n")
+{
+  struct isis_area *area;
+
+  area = vty->index;
+  if (!area)
+    {
+      vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE);
+      return CMD_ERR_NO_MATCH;
+    }
+
+  return area_set_lsp_mtu(vty, area, DEFAULT_LSP_MTU);
+}
+
+ALIAS(no_area_lsp_mtu,
+      no_area_lsp_mtu_arg_cmd,
+      "no lsp-mtu <128-4352>",
+      NO_STR
+      "Configure the maximum size of generated LSPs\n"
+      "Maximum size of generated LSPs\n");
+
 DEFUN (area_passwd_md5,
        area_passwd_md5_cmd,
        "area-password md5 WORD",
@@ -2991,6 +3059,12 @@ isis_config_write (struct vty *vty)
                write++;
              }
          }
+       if (area->lsp_mtu != DEFAULT_LSP_MTU)
+         {
+           vty_out(vty, " lsp-mtu %u%s", area->lsp_mtu, VTY_NEWLINE);
+           write++;
+         }
+
        /* Minimum SPF interval. */
        if (area->min_spf_interval[0] == area->min_spf_interval[1])
          {
@@ -3224,6 +3298,10 @@ isis_init ()
   install_element (ISIS_NODE, &is_type_cmd);
   install_element (ISIS_NODE, &no_is_type_cmd);
 
+  install_element (ISIS_NODE, &area_lsp_mtu_cmd);
+  install_element (ISIS_NODE, &no_area_lsp_mtu_cmd);
+  install_element (ISIS_NODE, &no_area_lsp_mtu_arg_cmd);
+
   install_element (ISIS_NODE, &area_passwd_md5_cmd);
   install_element (ISIS_NODE, &area_passwd_md5_snpauth_cmd);
   install_element (ISIS_NODE, &area_passwd_clear_cmd);
index efebed9ce85a75e9b83fa6f7e7ad7be4f27c55c1..ea5f0a9ce53beab4cc67263b07d86e55cd2256e3 100644 (file)
@@ -93,7 +93,8 @@ struct isis_area
   struct isis_spftree *spftree6[ISIS_LEVELS];    /* The v6 SPTs */
   struct route_table *route_table6[ISIS_LEVELS];  /* IPv6 routes */
 #endif
-  unsigned int min_bcast_mtu;
+#define DEFAULT_LSP_MTU 1497
+  unsigned int lsp_mtu;                                  /* Size of LSPs to generate */
   struct list *circuit_list;   /* IS-IS circuits */
   struct flags flags;
   struct thread *t_tick;       /* LSP walker */