Annotation of embedaddon/quagga/ripngd/ripng_nexthop.c, revision 1.1

1.1     ! misho       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
        !            17:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
        !            18:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
        !            19:  * 02111-1307, USA.  
        !            20:  */
        !            21: 
        !            22: /* This file is required in order to support properly the RIPng nexthop
        !            23:  * feature.
        !            24:  */
        !            25: 
        !            26: #include <zebra.h>
        !            27: 
        !            28: /* For struct udphdr. */
        !            29: #include <netinet/udp.h>
        !            30: 
        !            31: #include "linklist.h"
        !            32: #include "stream.h"
        !            33: #include "log.h"
        !            34: #include "memory.h"
        !            35: #include "vty.h"
        !            36: #include "if.h"
        !            37: #include "prefix.h"
        !            38: 
        !            39: #include "ripngd/ripngd.h"
        !            40: #include "ripngd/ripng_debug.h"
        !            41: #include "ripngd/ripng_nexthop.h"
        !            42: 
        !            43: #define DEBUG 1
        !            44: 
        !            45: #define min(a, b) ((a) < (b) ? (a) : (b))
        !            46: 
        !            47: struct ripng_rte_data {
        !            48:   struct prefix_ipv6 *p;
        !            49:   struct ripng_info *rinfo;
        !            50:   struct ripng_aggregate *aggregate;
        !            51: };
        !            52: 
        !            53: void _ripng_rte_del(struct ripng_rte_data *A);
        !            54: int _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B);
        !            55: 
        !            56: #define METRIC_OUT(a) \
        !            57:     ((a)->rinfo ?  (a)->rinfo->metric_out : (a)->aggregate->metric_out)
        !            58: #define NEXTHOP_OUT_PTR(a) \
        !            59:     ((a)->rinfo ?  &((a)->rinfo->nexthop_out) : &((a)->aggregate->nexthop_out))
        !            60: #define TAG_OUT(a) \
        !            61:     ((a)->rinfo ?  (a)->rinfo->tag_out : (a)->aggregate->tag_out)
        !            62: 
        !            63: struct list *
        !            64: ripng_rte_new(void) {
        !            65:   struct list *rte;
        !            66: 
        !            67:   rte = list_new();
        !            68:   rte->cmp = (int (*)(void *, void *)) _ripng_rte_cmp;
        !            69:   rte->del = (void (*)(void *)) _ripng_rte_del;
        !            70: 
        !            71:   return rte;
        !            72: }
        !            73: 
        !            74: void
        !            75: ripng_rte_free(struct list *ripng_rte_list) {
        !            76:   list_delete(ripng_rte_list);
        !            77: }
        !            78: 
        !            79: /* Delete RTE */
        !            80: void
        !            81: _ripng_rte_del(struct ripng_rte_data *A) {
        !            82:   XFREE(MTYPE_RIPNG_RTE_DATA, A);
        !            83: }
        !            84: 
        !            85: /* Compare RTE:
        !            86:  *  return +  if A > B
        !            87:  *         0  if A = B
        !            88:  *         -  if A < B
        !            89:  */
        !            90: int
        !            91: _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B) {
        !            92:   return addr6_cmp(NEXTHOP_OUT_PTR(A), NEXTHOP_OUT_PTR(B));
        !            93: }
        !            94: 
        !            95: /* Add routing table entry */
        !            96: void
        !            97: ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p,
        !            98:               struct ripng_info *rinfo, struct ripng_aggregate *aggregate) {
        !            99: 
        !           100:   struct ripng_rte_data *data;
        !           101: 
        !           102:   /* At least one should not be null */
        !           103:   assert(!rinfo || !aggregate);
        !           104: 
        !           105:   data = XMALLOC(MTYPE_RIPNG_RTE_DATA, sizeof(*data));
        !           106:   data->p     = p;
        !           107:   data->rinfo = rinfo;
        !           108:   data->aggregate = aggregate;
        !           109: 
        !           110:   listnode_add_sort(ripng_rte_list, data);
        !           111: } 
        !           112: 
        !           113: /* Send the RTE with the nexthop support
        !           114:  */
        !           115: void
        !           116: ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
        !           117:                struct sockaddr_in6 *to) {
        !           118: 
        !           119:   struct ripng_rte_data *data;
        !           120:   struct listnode *node, *nnode;
        !           121: 
        !           122:   struct in6_addr last_nexthop;
        !           123:   struct in6_addr myself_nexthop;
        !           124: 
        !           125:   struct stream *s;
        !           126:   int num;
        !           127:   int mtu;
        !           128:   int rtemax;
        !           129:   int ret;
        !           130: 
        !           131:   /* Most of the time, there is no nexthop */
        !           132:   memset(&last_nexthop, 0, sizeof(last_nexthop));
        !           133: 
        !           134:   /* Use myself_nexthop if the nexthop is not a link-local address, because
        !           135:    * we remain a right path without beeing the optimal one.
        !           136:    */
        !           137:   memset(&myself_nexthop, 0, sizeof(myself_nexthop));
        !           138: 
        !           139:   /* Output stream get from ripng structre.  XXX this should be
        !           140:      interface structure. */
        !           141:   s = ripng->obuf;
        !           142: 
        !           143:   /* Reset stream and RTE counter. */
        !           144:   stream_reset (s);
        !           145:   num = 0;
        !           146: 
        !           147:   mtu = ifp->mtu6;
        !           148:   if (mtu < 0)
        !           149:     mtu = IFMINMTU;
        !           150: 
        !           151:   rtemax = (min (mtu, RIPNG_MAX_PACKET_SIZE) -
        !           152:            IPV6_HDRLEN - 
        !           153:            sizeof (struct udphdr) -
        !           154:            sizeof (struct ripng_packet) +
        !           155:            sizeof (struct rte)) / sizeof (struct rte);
        !           156: 
        !           157:   for (ALL_LIST_ELEMENTS (ripng_rte_list, node, nnode, data)) {
        !           158:     /* (2.1) Next hop support */
        !           159:     if (!IPV6_ADDR_SAME(&last_nexthop, NEXTHOP_OUT_PTR(data))) {
        !           160: 
        !           161:       /* A nexthop entry should be at least followed by 1 RTE */
        !           162:       if (num == (rtemax-1)) {
        !           163:        ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s),
        !           164:                                 to, ifp);
        !           165: 
        !           166:         if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
        !           167:           ripng_packet_dump((struct ripng_packet *)STREAM_DATA (s),
        !           168:                            stream_get_endp(s), "SEND");
        !           169:         num = 0;
        !           170:         stream_reset (s);
        !           171:       }
        !           172: 
        !           173:       /* Add the nexthop (2.1) */
        !           174: 
        !           175:       /* If the received next hop address is not a link-local address,
        !           176:        * it should be treated as 0:0:0:0:0:0:0:0.
        !           177:        */
        !           178:       if (!IN6_IS_ADDR_LINKLOCAL(NEXTHOP_OUT_PTR(data)))
        !           179:         last_nexthop = myself_nexthop;
        !           180:       else
        !           181:        last_nexthop = *NEXTHOP_OUT_PTR(data);
        !           182: 
        !           183:       num = ripng_write_rte(num, s, NULL, &last_nexthop, 0, RIPNG_METRIC_NEXTHOP);
        !           184:     } else {
        !           185:       /* Rewrite the nexthop for each new packet */
        !           186:       if ((num == 0) && !IPV6_ADDR_SAME(&last_nexthop, &myself_nexthop))
        !           187:         num = ripng_write_rte(num, s, NULL, &last_nexthop, 0, RIPNG_METRIC_NEXTHOP);
        !           188:     }
        !           189:     num = ripng_write_rte(num, s, data->p, NULL,
        !           190:                          TAG_OUT(data), METRIC_OUT(data));
        !           191: 
        !           192:     if (num == rtemax) {
        !           193:       ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s),
        !           194:                               to, ifp);
        !           195: 
        !           196:       if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
        !           197:         ripng_packet_dump((struct ripng_packet *)STREAM_DATA (s),
        !           198:                          stream_get_endp(s), "SEND");
        !           199:       num = 0;
        !           200:       stream_reset (s);
        !           201:     }
        !           202:   }
        !           203: 
        !           204:   /* If unwritten RTE exist, flush it. */
        !           205:   if (num != 0) {
        !           206:     ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s),
        !           207:                             to, ifp);
        !           208: 
        !           209:     if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
        !           210:       ripng_packet_dump ((struct ripng_packet *)STREAM_DATA (s),
        !           211:                         stream_get_endp (s), "SEND");
        !           212:     num = 0;
        !           213:     stream_reset (s);
        !           214:   }
        !           215: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>