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

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:     stream_reset (s);
                    213:   }
                    214: }

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