On 23.01.2012 22:00, Ondrej Zajicek wrote:
On Mon, Jan 23, 2012 at 08:14:28PM +0400, Alexander V. Chernikov wrote:
On 23.01.2012 20:01, Maciej Wierzbicki wrote:
Hello.

Case study:
* importing full BGP table from various uplinks
* some routes received by BGP are being exported via OSPF to core1,
using filters:
(source = RTS_BGP&&  bgp_path ~ [= * ASNXYZ * =])

Question: how to aggregate routes (whenever possible) before exporting
them via OSPF to core?

It is not possible currently.

I'm working on BGP route aggregation and I plan to get more or less
working code at the end of this week.

Do you plan to integrate it to the BGP protocol? I don't think it is
This is separate protocol, of course.
a good idea. It would be easy to make generic route aggregation -
My first idea was to implement generic aggregation protocol.
However, do we really need it generic?
Currently we have bunch of link-state protocols (ISIS / OSPF) which are pure singletons, and, even if not we probably don't want to make summary routes between instances. RIP[ng] is RIP(c). There are also some multicast protocols but is is far-far away. Not sure if we should permit route aggregation from different protocol types.

'virtual' protocol similar to static, which generates aggregate routes
based on its config and received routes

Yes. I personally see this as following:

protocol abgp agg1 {
  aggregate address  1.2.3.0/24;
aggregate address 1.2.4.0/24 save attributes (or other keywords); # Aggregate as much attributes as possible ( see RFC 4271 9.2.2.2. ) # http://www.cisco.com/en/US/tech/tk365/technologies_tech_note09186a0080094826.shtml
  aggregate address 2.3.4.5.0/24 summary only;
  aggregate address 3.4.5.0/24 mandatory list { 3.4.5.1/32, 3.4.5.8/29};
  import filter somefilter; # Change summary route attributes
}

protocol bgp bgp1 {
  ..
  aggregator agg1;
}

Rte's matching 'summary only' instances have to be modified (no-export community have to be added to community attribute) by aggregator before passing them to rte_update

Mandatory list is a list of routes which have to exist before summary route is announced.

[BGP] protocols using aggregator will call rte_update_agg() instead of usual rte_update()

Aggregator stores its summary and mandatory routes in modified f_trie.
(
I think, there is no need to import/implement another tree if we can
modify current implementation:
e.g. use regular pools (flag passed to f_new_trie, along with node_size)
and add trie_remove_prefix
)


Possibly we have to implement some kind of lazy protocol name resolving.
I mean, add all "aggregator $proto_name" entries to linked-list with file/line data and do symbol lookup after configuration parsing is finished calling modified cf_error() if lookup fails.


Btw, I've got small patch from my previous approach, it moves default protocol preference to struct protocol and assigns it in proto_config_new instead of assigning it in every protocol manually.
Maybe it is a good candidate for the next commit? :)

--
Alexander V. Chernikov
Yandex NOC
>From ec7348269a785e9f1cc45cc3e1d940fd40bb7636 Mon Sep 17 00:00:00 2001
From: Alexander V. Chernikov <[email protected]>
Date: Thu, 12 Jan 2012 22:36:25 +0000
Subject: [PATCH 2/4] * Assign default protocol preference via proto_config_new()

---
 nest/config.Y         |    1 -
 nest/proto.c          |    1 +
 nest/protocol.h       |    1 +
 nest/rt-dev.c         |    1 +
 proto/bgp/bgp.c       |    1 +
 proto/bgp/config.Y    |    1 -
 proto/ospf/config.Y   |    1 -
 proto/ospf/ospf.c     |    1 +
 proto/pipe/config.Y   |    1 -
 proto/pipe/pipe.c     |    1 +
 proto/rip/rip.c       |    2 +-
 proto/static/static.c |    2 +-
 sysdep/unix/krt.Y     |    2 --
 sysdep/unix/krt.c     |    2 ++
 14 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/nest/config.Y b/nest/config.Y
index a6baf4e..3fcfa52 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -219,7 +219,6 @@ CF_ADDTO(proto, dev_proto '}')
 
 dev_proto_start: proto_start DIRECT {
      this_proto = proto_config_new(&proto_device, sizeof(struct 
rt_dev_config), $1);
-     this_proto->preference = DEF_PREF_DIRECT;
      init_list(&DIRECT_CFG->iface_list);
    }
  ;
diff --git a/nest/proto.c b/nest/proto.c
index d55c348..0fc72ce 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -200,6 +200,7 @@ proto_config_new(struct protocol *pr, unsigned size, int 
class)
   c->global = new_config;
   c->protocol = pr;
   c->name = pr->name;
+  c->preference = pr->preference;
   c->class = class;
   c->out_filter = FILTER_REJECT;
   c->table = c->global->master_rtc;
diff --git a/nest/protocol.h b/nest/protocol.h
index 3766e15..a83c4ff 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -39,6 +39,7 @@ struct protocol {
   char *template;                      /* Template for automatic generation of 
names */
   int name_counter;                    /* Counter for automatic name 
generation */
   int attr_class;                      /* Attribute class known to this 
protocol */
+  unsigned preference;                 /* Default protocol preference */
 
   void (*preconfig)(struct protocol *, struct config *);       /* Just before 
configuring */
   void (*postconfig)(struct proto_config *);                   /* After 
configuring each instance */
diff --git a/nest/rt-dev.c b/nest/rt-dev.c
index 497ee80..54cb14b 100644
--- a/nest/rt-dev.c
+++ b/nest/rt-dev.c
@@ -109,6 +109,7 @@ dev_copy_config(struct proto_config *dest, struct 
proto_config *src)
 struct protocol proto_device = {
   name:                "Direct",
   template:    "direct%d",
+  preference:  DEF_PREF_DIRECT,
   init:                dev_init,
   reconfigure: dev_reconfigure,
   copy_config: dev_copy_config
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 66fdc60..4d3c32f 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -1178,6 +1178,7 @@ struct protocol proto_bgp = {
   name:                        "BGP",
   template:            "bgp%d",
   attr_class:          EAP_BGP,
+  preference:          DEF_PREF_BGP,
   init:                        bgp_init,
   start:               bgp_start,
   shutdown:            bgp_shutdown,
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 5fb6094..78ca52d 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -33,7 +33,6 @@ CF_ADDTO(proto, bgp_proto '}' { bgp_check_config(BGP_CFG); } )
 
 bgp_proto_start: proto_start BGP {
      this_proto = proto_config_new(&proto_bgp, sizeof(struct bgp_config), $1);
-     this_proto->preference = DEF_PREF_BGP;
      BGP_CFG->hold_time = 240;
      BGP_CFG->connect_retry_time = 120;
      BGP_CFG->initial_hold_time = 240;
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y
index 4ada41e..24e125a 100644
--- a/proto/ospf/config.Y
+++ b/proto/ospf/config.Y
@@ -129,7 +129,6 @@ CF_ADDTO(proto, ospf_proto '}' { ospf_proto_finish(); } )
 
 ospf_proto_start: proto_start OSPF {
      this_proto = proto_config_new(&proto_ospf, sizeof(struct ospf_config), 
$1);
-     this_proto->preference = DEF_PREF_OSPF;
      init_list(&OSPF_CFG->area_list);
      init_list(&OSPF_CFG->vlink_list);
      OSPF_CFG->rfc1583 = DEFAULT_RFC1583;
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index ce7ad37..73c06c2 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -1542,6 +1542,7 @@ struct protocol proto_ospf = {
   name:                        "OSPF",
   template:            "ospf%d",
   attr_class:          EAP_OSPF,
+  preference:          DEF_PREF_OSPF,
   init:                        ospf_init,
   dump:                        ospf_dump,
   start:               ospf_start,
diff --git a/proto/pipe/config.Y b/proto/pipe/config.Y
index 4478afe..4063755 100644
--- a/proto/pipe/config.Y
+++ b/proto/pipe/config.Y
@@ -24,7 +24,6 @@ CF_ADDTO(proto, pipe_proto '}')
 
 pipe_proto_start: proto_start PIPE {
      this_proto = proto_config_new(&proto_pipe, sizeof(struct pipe_config), 
$1);
-     this_proto->preference = DEF_PREF_PIPE;
      PIPE_CFG->mode = PIPE_TRANSPARENT;
   }
  ;
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index 420c5a9..fe8618b 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -197,6 +197,7 @@ pipe_get_status(struct proto *P, byte *buf)
 struct protocol proto_pipe = {
   name:                "Pipe",
   template:    "pipe%d",
+  preference:  DEF_PREF_PIPE,
   postconfig:  pipe_postconfig,
   init:                pipe_init,
   start:       pipe_start,
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index 543aa30..f0a4134 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -975,7 +975,6 @@ void
 rip_init_config(struct rip_proto_config *c)
 {
   init_list(&c->iface_list);
-  c->c.preference = DEF_PREF_RIP;
   c->infinity  = 16;
   c->port      = 520;
   c->period    = 30;
@@ -1032,6 +1031,7 @@ struct protocol proto_rip = {
   name: "RIP",
   template: "rip%d",
   attr_class: EAP_RIP,
+  preference: DEF_PREF_RIP,
   get_route_info: rip_get_route_info,
   get_attr: rip_get_attr,
 
diff --git a/proto/static/static.c b/proto/static/static.c
index f6c2a33..aaa9bfa 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -353,7 +353,6 @@ static_if_notify(struct proto *p, unsigned flags, struct 
iface *i)
 void
 static_init_config(struct static_config *c)
 {
-  c->c.preference = DEF_PREF_STATIC;
   init_list(&c->iface_routes);
   init_list(&c->other_routes);
 }
@@ -523,6 +522,7 @@ static_copy_config(struct proto_config *dest, struct 
proto_config *src)
 struct protocol proto_static = {
   name:                "Static",
   template:    "static%d",
+  preference:  DEF_PREF_STATIC,
   init:                static_init,
   dump:                static_dump,
   start:       static_start,
diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y
index 8608196..18e1e52 100644
--- a/sysdep/unix/krt.Y
+++ b/sysdep/unix/krt.Y
@@ -31,7 +31,6 @@ kern_proto_start: proto_start KERNEL {
        cf_error("Kernel protocol already defined");
 #endif
      cf_krt = this_proto = proto_config_new(&proto_unix_kernel, sizeof(struct 
krt_config), $1);
-     this_proto->preference = DEF_PREF_INHERITED;
      THIS_KRT->scan_time = 60;
      THIS_KRT->learn = THIS_KRT->persist = 0;
      krt_scan_construct(THIS_KRT);
@@ -67,7 +66,6 @@ kif_proto_start: proto_start DEVICE {
      if (cf_kif)
        cf_error("Kernel device protocol already defined");
      cf_kif = this_proto = proto_config_new(&proto_unix_iface, sizeof(struct 
kif_config), $1);
-     this_proto->preference = DEF_PREF_DIRECT;
      THIS_KIF->scan_time = 60;
      init_list(&THIS_KIF->primary);
      krt_if_construct(THIS_KIF);
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index e5a8ce1..c4886c9 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -236,6 +236,7 @@ kif_copy_config(struct proto_config *dest, struct 
proto_config *src)
 struct protocol proto_unix_iface = {
   name:                "Device",
   template:    "device%d",
+  preference:  DEF_PREF_DIRECT,
   preconfig:   kif_preconfig,
   init:                kif_init,
   start:       kif_start,
@@ -961,6 +962,7 @@ struct protocol proto_unix_kernel = {
   name:                "Kernel",
   template:    "kernel%d",
   attr_class:  EAP_KRT,
+  preference:  DEF_PREF_INHERITED,
   preconfig:   krt_preconfig,
   postconfig:  krt_postconfig,
   init:                krt_init,
-- 
1.7.3.2

Reply via email to