Revision 538264cf

View differences:

nest/bfd.h
32 32
};
33 33

  
34 34

  
35
#define BFD_STATE_ADMIN_DOWN	0
36
#define BFD_STATE_DOWN		1
37
#define BFD_STATE_INIT		2
38
#define BFD_STATE_UP		3
39

  
40

  
35 41
#ifdef CONFIG_BFD
36 42

  
37 43
struct bfd_request * bfd_request_session(pool *p, ip_addr addr, ip_addr local, struct iface *iface, void (*hook)(struct bfd_request *), void *data);
proto/static/config.Y
16 16
static struct static_route *this_srt, *this_srt_nh, *last_srt_nh;
17 17
static struct f_inst **this_srt_last_cmd;
18 18

  
19
static void
20
static_route_finish(void)
21
{
22
  struct static_route *r;
23

  
24
  /* Update undefined use_bfd entries in multipath nexthops */
25
  if (this_srt->dest == RTD_MULTIPATH)
26
    for (r = this_srt->mp_next; r; r = r->mp_next)
27
      if (r->use_bfd < 0)
28
        r->use_bfd = this_srt->use_bfd;
29
}
30

  
19 31
CF_DECLS
20 32

  
21 33
CF_KEYWORDS(STATIC, ROUTE, VIA, DROP, REJECT, PROHIBIT, PREFERENCE, CHECK, LINK)
22
CF_KEYWORDS(MULTIPATH, WEIGHT, RECURSIVE, IGP, TABLE, BLACKHOLE, UNREACHABLE)
34
CF_KEYWORDS(MULTIPATH, WEIGHT, RECURSIVE, IGP, TABLE, BLACKHOLE, UNREACHABLE, BFD)
23 35

  
24 36

  
25 37
CF_GRAMMAR
......
37 49
 | static_proto proto_item ';'
38 50
 | static_proto CHECK LINK bool ';' { STATIC_CFG->check_link = $4; }
39 51
 | static_proto IGP TABLE rtable ';' { STATIC_CFG->igp_table = $4; }
40
 | static_proto stat_route stat_route_opt_list ';'
52
 | static_proto stat_route stat_route_opt_list ';' { static_route_finish(); }
41 53
 ;
42 54

  
43 55
stat_route0: ROUTE prefix {
......
57 69
     this_srt_nh->via = $2;
58 70
     this_srt_nh->via_if = $3;
59 71
     this_srt_nh->if_name = (void *) this_srt; /* really */
72
     this_srt_nh->use_bfd = -1; /* undefined */
60 73
   }
61 74
 | stat_multipath1 WEIGHT expr {
62 75
     this_srt_nh->masklen = $3 - 1; /* really */
63 76
     if (($3<1) || ($3>256)) cf_error("Weight must be in range 1-256"); 
64 77
   }
78
 | stat_multipath1 BFD bool {
79
     this_srt_nh->use_bfd = $3; cf_check_bfd($3);
80
   }
65 81
 ;
66 82

  
67 83
stat_multipath:
......
98 114

  
99 115
stat_route_item:
100 116
   cmd { *this_srt_last_cmd = $1; this_srt_last_cmd = &($1->next); }
117
 | BFD bool ';' { this_srt->use_bfd = $2; cf_check_bfd($2); }
101 118
 ;
102 119

  
103 120
stat_route_opts:
proto/static/static.c
141 141
  r->installed = 0;
142 142
}
143 143

  
144
static void
145
static_bfd_notify(struct bfd_request *req);
146

  
147
static void
148
static_update_bfd(struct proto *p, struct static_route *r)
149
{
150
  struct neighbor *nb = r->neigh;
151
  int bfd_up = (nb->scope > 0) && r->use_bfd;
152

  
153
  if (bfd_up && !r->bfd_req)
154
  {
155
    // ip_addr local = ipa_nonzero(r->local) ? r->local : nb->ifa->ip;
156
    r->bfd_req = bfd_request_session(p->pool, r->via, nb->ifa->ip, nb->iface,
157
				     static_bfd_notify, r);
158
  }
159

  
160
  if (!bfd_up && r->bfd_req)
161
  {
162
    rfree(r->bfd_req);
163
    r->bfd_req = NULL;
164
  }
165
}
166

  
144 167
static int
145 168
static_decide(struct static_config *cf, struct static_route *r)
146 169
{
......
153 176
  if (cf->check_link && !(r->neigh->iface->flags & IF_LINK_UP))
154 177
    return 0;
155 178

  
179
  if (r->bfd_req && r->bfd_req->state != BFD_STATE_UP)
180
    return 0;
181

  
156 182
  return 1;
157 183
}
158 184

  
......
171 197
	    r->chain = n->data;
172 198
	    n->data = r;
173 199
	    r->neigh = n;
200

  
201
	    static_update_bfd(p, r);
174 202
	    if (static_decide(cf, r))
175 203
	      static_install(p, r, n->iface);
176 204
	    else
......
200 228
		r2->chain = n->data;
201 229
		n->data = r2;
202 230
		r2->neigh = n;
231

  
232
		static_update_bfd(p, r2);
203 233
		r2->installed = static_decide(cf, r2);
204 234
		count += r2->installed;
205 235
	      }
......
222 252
    }
223 253
}
224 254

  
255
static void
256
static_rte_cleanup(struct proto *p, struct static_route *r)
257
{
258
  struct static_route *r2;
259

  
260
  if (r->bfd_req)
261
  {
262
    rfree(r->bfd_req);
263
    r->bfd_req = NULL;
264
  }
265

  
266
  if (r->dest == RTD_MULTIPATH)
267
    for (r2 = r->mp_next; r2; r2 = r2->mp_next)
268
      if (r2->bfd_req)
269
      {
270
	rfree(r2->bfd_req);
271
	r2->bfd_req = NULL;
272
      }
273
}
274

  
225 275
static int
226 276
static_start(struct proto *p)
227 277
{
......
254 304
  WALK_LIST(r, cf->iface_routes)
255 305
    r->installed = 0;
256 306
  WALK_LIST(r, cf->other_routes)
307
  {
308
    static_rte_cleanup(p, r);
257 309
    r->installed = 0;
310
  }
258 311

  
259 312
  return PS_DOWN;
260 313
}
......
268 321
    rt_unlock_table(cf->igp_table->table);
269 322
}
270 323

  
324
static void
325
static_update_rte(struct proto *p, struct static_route *r)
326
{
327
  switch (r->dest)
328
  {
329
  case RTD_ROUTER:
330
    if (static_decide((struct static_config *) p->cf, r))
331
      static_install(p, r, r->neigh->iface);
332
    else
333
      static_remove(p, r);
334
    break;
335

  
336
  case RTD_NONE: /* a part of multipath route */
337
  {
338
    int decision = static_decide((struct static_config *) p->cf, r);
339
    if (decision == r->installed)
340
      break; /* no change */
341
    r->installed = decision;
342

  
343
    struct static_route *r1, *r2;
344
    int count = 0;
345
    r1 = (void *) r->if_name; /* really */
346
    for (r2 = r1->mp_next; r2; r2 = r2->mp_next)
347
      count += r2->installed;
348

  
349
    if (count)
350
    {
351
      /* Set of nexthops changed - force reinstall */
352
      r1->installed = 0;
353
      static_install(p, r1, NULL);
354
    }
355
    else
356
      static_remove(p, r1);
357

  
358
    break;
359
  }
360
  }
361
}
271 362

  
272 363
static void
273 364
static_neigh_notify(struct neighbor *n)
......
277 368

  
278 369
  DBG("Static: neighbor notify for %I: iface %p\n", n->addr, n->iface);
279 370
  for(r=n->data; r; r=r->chain)
280
    switch (r->dest)
281
      {
282
      case RTD_ROUTER:
283
	if (static_decide((struct static_config *) p->cf, r))
284
	  static_install(p, r, n->iface);
285
	else
286
	  static_remove(p, r);
287
	break;
371
  {
372
    static_update_bfd(p, r);
373
    static_update_rte(p, r);
374
  }
375
}
288 376

  
289
      case RTD_NONE: /* a part of multipath route */
290
	{
291
	  int decision = static_decide((struct static_config *) p->cf, r);
292
	  if (decision == r->installed)
293
	    break; /* no change */
294
	  r->installed = decision;
295

  
296
	  struct static_route *r1, *r2;
297
	  int count = 0;
298
	  r1 = (void *) r->if_name; /* really */
299
	  for (r2 = r1->mp_next; r2; r2 = r2->mp_next)
300
	    count += r2->installed;
301

  
302
	  if (count)
303
	    {
304
	      /* Set of nexthops changed - force reinstall */
305
	      r1->installed = 0;
306
	      static_install(p, r1, NULL);
307
	    }
308
	  else
309
	    static_remove(p, r1);
377
static void
378
static_bfd_notify(struct bfd_request *req)
379
{
380
  struct static_route *r = req->data;
381
  struct proto *p = r->neigh->proto;
310 382

  
311
	  break;
312
	}
313
      }
383
  // if (req->down) TRACE(D_EVENTS, "BFD session down for nbr %I on %s", XXXX);
384

  
385
  static_update_rte(p, r);
314 386
}
315 387

  
316 388
static void
......
414 486
      for (x = x->mp_next, y = y->mp_next;
415 487
	   x && y;
416 488
	   x = x->mp_next, y = y->mp_next)
417
	if (!ipa_equal(x->via, y->via) || (x->via_if != y->via_if))
489
	if (!ipa_equal(x->via, y->via) || (x->via_if != y->via_if) || (x->use_bfd != y->use_bfd))
418 490
	  return 0;
419 491
      return !x && !y;
420 492

  
......
499 571
  WALK_LIST(r, n->other_routes)
500 572
    static_add(p, n, r);
501 573

  
574
  WALK_LIST(r, o->other_routes)
575
    static_rte_cleanup(p, r);
576

  
502 577
  return 1;
503 578
}
504 579

  
......
584 659
    case RTDX_RECURSIVE: bsprintf(via, "recursive %I", r->via); break;
585 660
    default:		bsprintf(via, "???");
586 661
    }
587
  cli_msg(-1009, "%I/%d %s%s", r->net, r->masklen, via, r->installed ? "" : " (dormant)");
662
  cli_msg(-1009, "%I/%d %s%s%s", r->net, r->masklen, via,
663
	  r->bfd_req ? " (bfd)" : "", r->installed ? "" : " (dormant)");
588 664

  
589 665
  struct static_route *r2;
590 666
  if (r->dest == RTD_MULTIPATH)
591 667
    for (r2 = r->mp_next; r2; r2 = r2->mp_next)
592
      cli_msg(-1009, "\tvia %I%J weight %d%s", r2->via, r2->via_if, r2->masklen + 1, /* really */
593
	      r2->installed ? "" : " (dormant)");
668
      cli_msg(-1009, "\tvia %I%J weight %d%s%s", r2->via, r2->via_if, r2->masklen + 1, /* really */
669
	      r2->bfd_req ? " (bfd)" : "", r2->installed ? "" : " (dormant)");
594 670
}
595 671

  
596 672
void
proto/static/static.h
9 9
#ifndef _BIRD_STATIC_H_
10 10
#define _BIRD_STATIC_H_
11 11

  
12
#include "nest/route.h"
13
#include "nest/bfd.h"
14

  
12 15
struct static_config {
13 16
  struct proto_config c;
14 17
  list iface_routes;		/* Routes to search on interface events */
......
33 36
  struct static_route *mp_next;		/* Nexthops for RTD_MULTIPATH routes */
34 37
  struct f_inst *cmds;			/* List of commands for setting attributes */
35 38
  int installed;			/* Installed in rt table, -1 for reinstall */
39
  int use_bfd;				/* Configured to use BFD */
40
  struct bfd_request *bfd_req;		/* BFD request, if BFD is used */
36 41
};
37 42

  
38 43
/* Dummy nodes (parts of multipath route) abuses masklen field for weight

Also available in: Unified diff