back to topotato report
topotato coverage report
Current view: top level - ripngd - ripng_nexthop.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 1 82 1.2 %
Date: 2023-02-24 14:41:08 Functions: 2 8 25.0 %

          Line data    Source code
       1             : /* RIPngd Zebra
       2             :  * Copyright (C) 2002 6WIND <vincent.jardin@6wind.com>
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : /* This file is required in order to support properly the RIPng nexthop
      22             :  * feature.
      23             :  */
      24             : 
      25             : #include <zebra.h>
      26             : 
      27             : /* For struct udphdr. */
      28             : #include <netinet/udp.h>
      29             : 
      30             : #include "linklist.h"
      31             : #include "stream.h"
      32             : #include "log.h"
      33             : #include "memory.h"
      34             : #include "vty.h"
      35             : #include "if.h"
      36             : #include "prefix.h"
      37             : 
      38             : #include "ripngd/ripngd.h"
      39             : #include "ripngd/ripng_debug.h"
      40             : #include "ripngd/ripng_nexthop.h"
      41             : 
      42           3 : DEFINE_MTYPE_STATIC(RIPNGD, RIPNG_RTE_DATA, "RIPng rte data");
      43             : 
      44             : #define DEBUG 1
      45             : 
      46             : struct ripng_rte_data {
      47             :         struct prefix_ipv6 *p;
      48             :         struct ripng_info *rinfo;
      49             :         struct ripng_aggregate *aggregate;
      50             : };
      51             : 
      52             : void _ripng_rte_del(struct ripng_rte_data *A);
      53             : int _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B);
      54             : 
      55             : #define METRIC_OUT(a)                                                          \
      56             :         ((a)->rinfo ? (a)->rinfo->metric_out : (a)->aggregate->metric_out)
      57             : #define NEXTHOP_OUT_PTR(a)                                                     \
      58             :         ((a)->rinfo ? &((a)->rinfo->nexthop_out)                               \
      59             :                     : &((a)->aggregate->nexthop_out))
      60             : #define TAG_OUT(a) ((a)->rinfo ? (a)->rinfo->tag_out : (a)->aggregate->tag_out)
      61             : 
      62           0 : struct list *ripng_rte_new(void)
      63             : {
      64           0 :         struct list *rte;
      65             : 
      66           0 :         rte = list_new();
      67           0 :         rte->cmp = (int (*)(void *, void *))_ripng_rte_cmp;
      68           0 :         rte->del = (void (*)(void *))_ripng_rte_del;
      69             : 
      70           0 :         return rte;
      71             : }
      72             : 
      73           0 : void ripng_rte_free(struct list *ripng_rte_list)
      74             : {
      75           0 :         list_delete(&ripng_rte_list);
      76           0 : }
      77             : 
      78             : /* Delete RTE */
      79           0 : void _ripng_rte_del(struct ripng_rte_data *A)
      80             : {
      81           0 :         XFREE(MTYPE_RIPNG_RTE_DATA, A);
      82           0 : }
      83             : 
      84             : /* Compare RTE:
      85             :  *  return +  if A > B
      86             :  *         0  if A = B
      87             :  *         -  if A < B
      88             :  */
      89           0 : int _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B)
      90             : {
      91           0 :         return addr6_cmp(NEXTHOP_OUT_PTR(A), NEXTHOP_OUT_PTR(B));
      92             : }
      93             : 
      94             : /* Add routing table entry */
      95           0 : void ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p,
      96             :                    struct ripng_info *rinfo, struct ripng_aggregate *aggregate)
      97             : {
      98             : 
      99           0 :         struct ripng_rte_data *data;
     100             : 
     101             :         /* At least one should not be null */
     102           0 :         assert(!rinfo || !aggregate);
     103             : 
     104           0 :         data = XMALLOC(MTYPE_RIPNG_RTE_DATA, sizeof(*data));
     105           0 :         data->p = p;
     106           0 :         data->rinfo = rinfo;
     107           0 :         data->aggregate = aggregate;
     108             : 
     109           0 :         listnode_add_sort(ripng_rte_list, data);
     110           0 : }
     111             : 
     112             : /* Send the RTE with the nexthop support
     113             :  */
     114           0 : void ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
     115             :                     struct sockaddr_in6 *to)
     116             : {
     117           0 :         struct ripng_interface *ri = ifp->info;
     118           0 :         struct ripng *ripng = ri->ripng;
     119           0 :         struct ripng_rte_data *data;
     120           0 :         struct listnode *node, *nnode;
     121             : 
     122           0 :         struct in6_addr last_nexthop;
     123           0 :         struct in6_addr myself_nexthop;
     124             : 
     125           0 :         struct stream *s;
     126           0 :         int num;
     127           0 :         int mtu;
     128           0 :         int rtemax;
     129           0 :         int ret;
     130             : 
     131             :         /* Most of the time, there is no nexthop */
     132           0 :         memset(&last_nexthop, 0, sizeof(last_nexthop));
     133             : 
     134             :         /* Use myself_nexthop if the nexthop is not a link-local address,
     135             :          * because
     136             :          * we remain a right path without beeing the optimal one.
     137             :          */
     138           0 :         memset(&myself_nexthop, 0, sizeof(myself_nexthop));
     139             : 
     140             :         /* Output stream get from ripng structre.  XXX this should be
     141             :            interface structure. */
     142           0 :         s = ripng->obuf;
     143             : 
     144             :         /* Reset stream and RTE counter. */
     145           0 :         stream_reset(s);
     146           0 :         num = 0;
     147             : 
     148           0 :         mtu = ifp->mtu6;
     149           0 :         if (mtu < 0)
     150           0 :                 mtu = IFMINMTU;
     151             : 
     152           0 :         rtemax = (MIN(mtu, RIPNG_MAX_PACKET_SIZE) - IPV6_HDRLEN
     153             :                   - sizeof(struct udphdr) - sizeof(struct ripng_packet)
     154           0 :                   + sizeof(struct rte))
     155           0 :                  / sizeof(struct rte);
     156             : 
     157           0 :         for (ALL_LIST_ELEMENTS(ripng_rte_list, node, nnode, data)) {
     158             :                 /* (2.1) Next hop support */
     159           0 :                 if (!IPV6_ADDR_SAME(&last_nexthop, NEXTHOP_OUT_PTR(data))) {
     160             : 
     161             :                         /* A nexthop entry should be at least followed by 1 RTE
     162             :                          */
     163           0 :                         if (num == (rtemax - 1)) {
     164           0 :                                 ret = ripng_send_packet((caddr_t)STREAM_DATA(s),
     165           0 :                                                         stream_get_endp(s), to,
     166             :                                                         ifp);
     167             : 
     168           0 :                                 if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
     169           0 :                                         ripng_packet_dump(
     170             :                                                 (struct ripng_packet *)
     171             :                                                         STREAM_DATA(s),
     172           0 :                                                 stream_get_endp(s), "SEND");
     173           0 :                                 num = 0;
     174           0 :                                 stream_reset(s);
     175             :                         }
     176             : 
     177             :                         /* Add the nexthop (2.1) */
     178             : 
     179             :                         /* If the received next hop address is not a link-local
     180             :                          * address,
     181             :                          * it should be treated as 0:0:0:0:0:0:0:0.
     182             :                          */
     183           0 :                         if (!IN6_IS_ADDR_LINKLOCAL(NEXTHOP_OUT_PTR(data)))
     184           0 :                                 last_nexthop = myself_nexthop;
     185             :                         else
     186           0 :                                 last_nexthop = *NEXTHOP_OUT_PTR(data);
     187             : 
     188           0 :                         num = ripng_write_rte(num, s, NULL, &last_nexthop, 0,
     189             :                                               RIPNG_METRIC_NEXTHOP);
     190             :                 } else {
     191             :                         /* Rewrite the nexthop for each new packet */
     192           0 :                         if ((num == 0)
     193           0 :                             && !IPV6_ADDR_SAME(&last_nexthop, &myself_nexthop))
     194           0 :                                 num = ripng_write_rte(num, s, NULL,
     195             :                                                       &last_nexthop, 0,
     196             :                                                       RIPNG_METRIC_NEXTHOP);
     197             :                 }
     198           0 :                 num = ripng_write_rte(num, s, data->p, NULL, TAG_OUT(data),
     199           0 :                                       METRIC_OUT(data));
     200             : 
     201           0 :                 if (num == rtemax) {
     202           0 :                         ret = ripng_send_packet((caddr_t)STREAM_DATA(s),
     203           0 :                                                 stream_get_endp(s), to, ifp);
     204             : 
     205           0 :                         if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
     206           0 :                                 ripng_packet_dump(
     207             :                                         (struct ripng_packet *)STREAM_DATA(s),
     208           0 :                                         stream_get_endp(s), "SEND");
     209           0 :                         num = 0;
     210           0 :                         stream_reset(s);
     211             :                 }
     212             :         }
     213             : 
     214             :         /* If unwritten RTE exist, flush it. */
     215           0 :         if (num != 0) {
     216           0 :                 ret = ripng_send_packet((caddr_t)STREAM_DATA(s),
     217           0 :                                         stream_get_endp(s), to, ifp);
     218             : 
     219           0 :                 if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
     220           0 :                         ripng_packet_dump((struct ripng_packet *)STREAM_DATA(s),
     221           0 :                                           stream_get_endp(s), "SEND");
     222           0 :                 stream_reset(s);
     223             :         }
     224           0 : }

Generated by: LCOV version v1.16-topotato