diff options
Diffstat (limited to 'proto/ospf')
-rw-r--r-- | proto/ospf/config.Y | 6 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 73 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 6 | ||||
-rw-r--r-- | proto/ospf/topology.c | 32 | ||||
-rw-r--r-- | proto/ospf/topology.h | 2 |
5 files changed, 92 insertions, 27 deletions
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index dcd7500..9574141 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -12,7 +12,7 @@ CF_HDR CF_DECLS -CF_KEYWORDS(OSPF, AREA) +CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG) CF_GRAMMAR @@ -35,6 +35,10 @@ ospf_area: AREA idval { } ; +CF_ADDTO(dynamic_attr, OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC1); }) +CF_ADDTO(dynamic_attr, OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC2); }) +CF_ADDTO(dynamic_attr, OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_TAG); }) + CF_CODE CF_END diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 49e0233..b385a48 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -63,12 +63,13 @@ ospf_init(struct proto_config *c) struct proto_ospf *po=(struct proto_ospf *)p; debug("OSPF: Init requested.\n"); - p->neigh_notify = NULL; p->import_control = ospf_import_control; + p->make_tmp_attrs = ospf_make_tmp_attrs; + p->store_tmp_attrs = ospf_store_tmp_attrs; p->rt_notify = ospf_rt_notify; p->if_notify = ospf_if_notify; - p->rte_better=ospf_rte_better; - p->rte_same=ospf_rte_same; + p->rte_better = ospf_rte_better; + p->rte_same = ospf_rte_same; return p; } @@ -104,12 +105,34 @@ ospf_rte_better(struct rte *new, struct rte *old) static int ospf_rte_same(struct rte *new, struct rte *old) { - struct proto *p = new->attrs->proto; + /* new->attrs == old->attrs always */ + return + new->u.ospf.metric1 == old->u.ospf.metric1 && + new->u.ospf.metric2 == old->u.ospf.metric2 && + new->u.ospf.tag == old->u.ospf.tag; +} - if(new->attrs->source!=old->attrs->source) return 0; - if(new->u.ospf.metric1!=old->u.ospf.metric1) return 0; - if(new->u.ospf.metric2!=old->u.ospf.metric2) return 0; - return 1; +static ea_list * +ospf_build_attrs(ea_list *next, struct linpool *pool, u32 m1, u32 m2, u32 tag) +{ + struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 3*sizeof(eattr)); + + l->next = next; + l->flags = EALF_SORTED; + l->count = 3; + l->attrs[0].id = EA_OSPF_METRIC1; + l->attrs[0].flags = 0; + l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP; + l->attrs[0].u.data = m1; + l->attrs[1].id = EA_OSPF_METRIC2; + l->attrs[1].flags = 0; + l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP; + l->attrs[1].u.data = m2; + l->attrs[2].id = EA_OSPF_TAG; + l->attrs[2].flags = 0; + l->attrs[2].type = EAF_TYPE_INT | EAF_TEMP; + l->attrs[2].u.data = tag; + return l; } int @@ -118,9 +141,23 @@ ospf_import_control(struct proto *p, rte **new, ea_list **attrs, struct linpool rte *e=*new; struct proto_ospf *po=(struct proto_ospf *)p; - if(p==e->attrs->proto) return -1; + if(p==e->attrs->proto) return -1; /* Reject our own routes */ + *attrs = ospf_build_attrs(*attrs, pool, 0, 0, 0); /* FIXME: Use better defaults? */ + return 0; /* Leave decision to the filters */ +} - return 0; +struct ea_list * +ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool) +{ + return ospf_build_attrs(NULL, pool, rt->u.ospf.metric1, rt->u.ospf.metric2, rt->u.ospf.tag); +} + +void +ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs) +{ + rt->u.ospf.metric1 = ea_get_int(attrs, EA_OSPF_METRIC1, 0); + rt->u.ospf.metric2 = ea_get_int(attrs, EA_OSPF_METRIC2, 0); + rt->u.ospf.tag = ea_get_int(attrs, EA_OSPF_TAG, 0); } static int @@ -152,7 +189,7 @@ ospf_rt_notify(struct proto *p, net *n, rte *new, rte *old, ea_list *attrs) if(new) /* Got some new route */ { - originate_ext_lsa(n, new, po); + originate_ext_lsa(n, new, po, attrs); } else { @@ -210,13 +247,27 @@ ospf_get_route_info(rte *rte, byte *buf, ea_list *attrs) (rte->u.ospf.metric2==0) ? rte->u.ospf.metric1 : rte->u.ospf.metric2); } +static int +ospf_get_attr(eattr *a, byte *buf) +{ + switch (a->id) + { + case EA_OSPF_METRIC1: bsprintf(buf, "metric1"); return GA_NAME; + case EA_OSPF_METRIC2: bsprintf(buf, "metric2"); return GA_NAME; + case EA_OSPF_TAG: bsprintf(buf, "tag: %08x", a->u.data); return GA_FULL; + default: return GA_UNKNOWN; + } +} + struct protocol proto_ospf = { name: "OSPF", template: "ospf%d", + attr_class: EAP_OSPF, init: ospf_init, dump: ospf_dump, start: ospf_start, shutdown: ospf_shutdown, get_route_info: ospf_get_route_info, + get_attr: ospf_get_attr, get_status: ospf_get_status }; diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 0eaf98b..63c4fc2 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -353,8 +353,14 @@ static int ospf_rte_better(struct rte *new, struct rte *old); static int ospf_rte_same(struct rte *new, struct rte *old); int ospf_import_control(struct proto *p, rte **new, ea_list **attrs, struct linpool *pool); +struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool); +void ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs); void ospf_rt_notify(struct proto *p, net *n, rte *new, rte *old,ea_list *attrs); +#define EA_OSPF_METRIC1 EA_CODE(EAP_OSPF, 0) +#define EA_OSPF_METRIC2 EA_CODE(EAP_OSPF, 1) +#define EA_OSPF_TAG EA_CODE(EAP_OSPF, 2) + #include "proto/ospf/hello.h" #include "proto/ospf/packet.h" #include "proto/ospf/iface.h" diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 053ea4b..bb3cb06 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -319,38 +319,42 @@ originate_net_lsa(struct ospf_iface *ifa, struct proto_ospf *po) flood_lsa(NULL,NULL,&ifa->nlsa->lsa,po,NULL,ifa->oa,1); } -void * -originate_ext_lsa_body(net *n, rte *e, struct proto_ospf *po) +static void * +originate_ext_lsa_body(net *n, rte *e, struct proto_ospf *po, struct ea_list *attrs) { struct proto *p=&po->proto; struct ospf_lsa_ext *ext; struct ospf_lsa_ext_tos *et; neighbor *nn; + u32 m1 = ea_get_int(attrs, EA_OSPF_METRIC1, 0); + u32 m2 = ea_get_int(attrs, EA_OSPF_METRIC2, 0); + u32 tag = ea_get_int(attrs, EA_OSPF_TAG, 0); ext=mb_alloc(p->pool,sizeof(struct ospf_lsa_ext)+ sizeof(struct ospf_lsa_ext_tos)); ext->netmask=ipa_mkmask(n->n.pxlen); et=(struct ospf_lsa_ext_tos *)(ext+1); - if(e->u.ospf.metric2!=0) - { - et->etos=0; - et->metric=e->u.ospf.metric1; - } + + if(!m2) + { + et->etos=0; + et->metric=m1; + } else - { - et->etos=1; - et->metric=e->u.ospf.metric2; - } + { + et->etos=0x80; + et->metric=m2; + } et->padding=0; - et->tag=e->u.ospf.tag; + et->tag=tag; if(1) et->fwaddr= ipa_from_u32(0); /* FIXME if e->attrs->iface is not in my AS*/ else et->fwaddr=e->attrs->gw; return ext; } void -originate_ext_lsa(net *n, rte *e, struct proto_ospf *po) +originate_ext_lsa(net *n, rte *e, struct proto_ospf *po, struct ea_list *attrs) { struct ospf_lsa_header lsa; u32 rtid=po->proto.cf->global->router_id; @@ -366,7 +370,7 @@ originate_ext_lsa(net *n, rte *e, struct proto_ospf *po) lsa.type=LSA_T_EXT; lsa.rt=rtid; lsa.sn=LSA_INITSEQNO; - body=originate_ext_lsa_body(n, e, po); + body=originate_ext_lsa_body(n, e, po, attrs); lsa.length=sizeof(struct ospf_lsa_ext)+sizeof(struct ospf_lsa_ext_tos)+ sizeof(struct ospf_lsa_header); lsasum_calculate(&lsa,body,po); diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h index 23620b8..fe0d86e 100644 --- a/proto/ospf/topology.h +++ b/proto/ospf/topology.h @@ -49,6 +49,6 @@ void addifa_rtlsa(struct ospf_iface *ifa); void originate_rt_lsa(struct ospf_area *oa,struct proto_ospf *po); void originate_net_lsa(struct ospf_iface *ifa,struct proto_ospf *po); int can_flush_lsa(struct ospf_area *oa); -void originate_ext_lsa(net *n, rte *e, struct proto_ospf *po); +void originate_ext_lsa(net *n, rte *e, struct proto_ospf *po, struct ea_list *attrs); #endif /* _BIRD_OSPF_TOPOLOGY_H_ */ |