Statistics
| Branch: | Revision:

iof-bird-daemon / nest / rt-table.c @ 0cdbd397

History | View | Annotate | Download (4.05 KB)

1
/*
2
 *        BIRD -- Routing Table
3
 *
4
 *        (c) 1998 Martin Mares <mj@ucw.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9
#include <string.h>
10

    
11
#include "nest/bird.h"
12
#include "nest/route.h"
13
#include "nest/protocol.h"
14
#include "lib/resource.h"
15

    
16
rtable master_table;
17
static slab *rte_slab;
18

    
19
void
20
rte_init(struct fib_node *N)
21
{
22
  net *n = (net *) N;
23

    
24
  n->next = NULL;
25
  n->routes = NULL;
26
}
27

    
28
void
29
rt_setup(rtable *t, char *name)
30
{
31
  bzero(t, sizeof(*t));
32
  fib_init(&t->fib, &root_pool, sizeof(rte), 0, rte_init);
33
  t->name = name;
34
}
35

    
36
net *
37
net_find(rtable *tab, unsigned tos, ip_addr mask, unsigned len)
38
{
39
  while (tab && tab->tos != tos)
40
    tab = tab->sibling;
41
  if (!tab)
42
    return NULL;
43
  return (net *) fib_find(&tab->fib, &mask, len);
44
}
45

    
46
net *
47
net_get(rtable *tab, unsigned tos, ip_addr mask, unsigned len)
48
{
49
  rtable *t = tab;
50

    
51
  while (t && t->tos != tos)
52
    t = t->sibling;
53
  if (!t)
54
    {
55
      while (tab->sibling)
56
        tab = tab->sibling;
57
      t = mb_alloc(&root_pool, sizeof(rtable));
58
      rt_setup(t, NULL);
59
      tab->sibling = t;
60
      t->tos = tos;
61
    }
62
  return (net *) fib_get(&t->fib, &mask, len);
63
}
64

    
65
rte *
66
rte_find(net *net, struct proto *p)
67
{
68
  rte *e = net->routes;
69

    
70
  while (e && e->attrs->proto != p)
71
    e = e->next;
72
  return e;
73
}
74

    
75
rte *
76
rte_get_temp(rta *a)
77
{
78
  rte *e = sl_alloc(rte_slab);
79

    
80
  e->attrs = a;
81
  e->flags = 0;
82
  e->pref = a->proto->preference;
83
  e->lastmod = 0;                        /* FIXME */
84
  return e;
85
}
86

    
87
static int                                /* Actually better or at least as good as */
88
rte_better(rte *new, rte *old)
89
{
90
  int (*better)(rte *, rte *);
91

    
92
  if (!old)
93
    return 1;
94
  if (new->pref > old->pref)
95
    return 1;
96
  if (new->pref < old->pref)
97
    return 0;
98
  if (new->attrs->proto != old->attrs->proto)
99
    {
100
      /* FIXME!!! */
101
      die("Different protocols, but identical preferences => oops");
102
    }
103
  if (better = new->attrs->proto->rte_better)
104
    return better(new, old);
105
  return 0;
106
}
107

    
108
void
109
rte_announce(rte *new, rte *old)
110
{
111
  struct proto *p;
112

    
113
  WALK_LIST(p, proto_list)
114
    if (!new || new->attrs->proto != p)
115
      if (p->rt_notify)
116
        p->rt_notify(p, new, old);
117
}
118

    
119
static inline void
120
rte_free(rte *e)
121
{
122
  rta_free(e->attrs);
123
  sl_free(rte_slab, e);
124
}
125

    
126
void
127
rte_update(net *net, struct proto *p, rte *new)
128
{
129
  rte *old_best = net->routes;
130
  rte *old = NULL;
131
  rte **k, *r, *s;
132

    
133
  k = &net->routes;                        /* Find and remove original route from the same protocol */
134
  while (old = *k)
135
    {
136
      if (old->attrs->proto == p)
137
        {
138
          *k = old->next;
139
          break;
140
        }
141
      k = &old->next;
142
    }
143

    
144
  if (new && rte_better(new, old_best))        /* It's a new optimal route => announce and relink it */
145
    {
146
      rte_announce(new, old_best);
147
      new->next = net->routes;
148
      net->routes = new;
149
    }
150
  else
151
    {
152
      if (old == old_best)                /* It has _replaced_ the old optimal route */
153
        {
154
          r = new;                        /* Find new optimal route and announce it */
155
          for(s=net->routes; s; s=s->next)
156
            if (rte_better(s, r))
157
              r = s;
158
          rte_announce(r, old_best);
159
          if (r)                        /* Re-link the new optimal route */
160
            {
161
              k = &net->routes;
162
              while (s = *k)
163
                {
164
                  if (s == r)
165
                    {
166
                      *k = r->next;
167
                      break;
168
                    }
169
                }
170
              r->next = net->routes;
171
              net->routes = r;
172
            }
173
        }
174
      if (new)                                /* Link in the new non-optimal route */
175
        {
176
          new->next = old_best->next;
177
          old_best->next = new;
178
        }
179
    }
180
  if (old)
181
    rte_free(old);
182
}
183

    
184
void
185
rte_dump(net *n, rte *e)
186
{
187
  if (n)
188
    debug("%08x/%2d ", _I(n->n.prefix), n->n.pxlen);
189
  debug("PF=%02x pref=%d lm=%d ", e->pflags, e->pref, e->lastmod);
190
  rta_dump(e->attrs);
191
  if (e->flags & REF_CHOSEN)
192
    debug(" [*]");
193
  debug("\n");
194
}
195

    
196
void
197
rt_dump(rtable *t)
198
{
199
  rte *e;
200
  net *n;
201

    
202
  debug("Dump of routing table <%s>\n", t->name);
203
  while (t)
204
    {
205
      debug("Routes for TOS %02x:\n", t->tos);
206
      FIB_WALK(&t->fib, fn)
207
        {
208
          n = (net *) fn;
209
          for(e=n->routes; e; e=e->next)
210
            rte_dump(n, e);
211
        }
212
      FIB_WALK_END;
213
      t = t->sibling;
214
    }
215
  debug("\n");
216
}
217

    
218
void
219
rt_dump_all(void)
220
{
221
  rt_dump(&master_table);
222
}
223

    
224
void
225
rt_init(void)
226
{
227
  rta_init();
228
  rt_setup(&master_table, "master");
229
  rte_slab = sl_new(&root_pool, sizeof(rte));
230
}