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>