Route attributes for OSPF.
This commit is contained in:
parent
2cec475b8f
commit
5919c66e8f
6 changed files with 94 additions and 28 deletions
|
@ -287,7 +287,8 @@ typedef struct eattr {
|
||||||
#define EAP_GENERIC 0 /* Generic attributes */
|
#define EAP_GENERIC 0 /* Generic attributes */
|
||||||
#define EAP_BGP 1 /* BGP attributes */
|
#define EAP_BGP 1 /* BGP attributes */
|
||||||
#define EAP_RIP 2 /* RIP */
|
#define EAP_RIP 2 /* RIP */
|
||||||
#define EAP_MAX 3
|
#define EAP_OSPF 3 /* OSPF */
|
||||||
|
#define EAP_MAX 4
|
||||||
|
|
||||||
#define EA_CODE(proto,id) (((proto) << 8) | (id))
|
#define EA_CODE(proto,id) (((proto) << 8) | (id))
|
||||||
#define EA_PROTO(ea) ((ea) >> 8)
|
#define EA_PROTO(ea) ((ea) >> 8)
|
||||||
|
|
|
@ -12,7 +12,7 @@ CF_HDR
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(OSPF, AREA)
|
CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG)
|
||||||
|
|
||||||
CF_GRAMMAR
|
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_CODE
|
||||||
|
|
||||||
CF_END
|
CF_END
|
||||||
|
|
|
@ -63,8 +63,9 @@ ospf_init(struct proto_config *c)
|
||||||
struct proto_ospf *po=(struct proto_ospf *)p;
|
struct proto_ospf *po=(struct proto_ospf *)p;
|
||||||
|
|
||||||
debug("OSPF: Init requested.\n");
|
debug("OSPF: Init requested.\n");
|
||||||
p->neigh_notify = NULL;
|
|
||||||
p->import_control = ospf_import_control;
|
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->rt_notify = ospf_rt_notify;
|
||||||
p->if_notify = ospf_if_notify;
|
p->if_notify = ospf_if_notify;
|
||||||
p->rte_better = ospf_rte_better;
|
p->rte_better = ospf_rte_better;
|
||||||
|
@ -104,12 +105,34 @@ ospf_rte_better(struct rte *new, struct rte *old)
|
||||||
static int
|
static int
|
||||||
ospf_rte_same(struct rte *new, struct rte *old)
|
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;
|
static ea_list *
|
||||||
if(new->u.ospf.metric1!=old->u.ospf.metric1) return 0;
|
ospf_build_attrs(ea_list *next, struct linpool *pool, u32 m1, u32 m2, u32 tag)
|
||||||
if(new->u.ospf.metric2!=old->u.ospf.metric2) return 0;
|
{
|
||||||
return 1;
|
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
|
int
|
||||||
|
@ -118,9 +141,23 @@ ospf_import_control(struct proto *p, rte **new, ea_list **attrs, struct linpool
|
||||||
rte *e=*new;
|
rte *e=*new;
|
||||||
struct proto_ospf *po=(struct proto_ospf *)p;
|
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
|
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 */
|
if(new) /* Got some new route */
|
||||||
{
|
{
|
||||||
originate_ext_lsa(n, new, po);
|
originate_ext_lsa(n, new, po, attrs);
|
||||||
}
|
}
|
||||||
else
|
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);
|
(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 = {
|
struct protocol proto_ospf = {
|
||||||
name: "OSPF",
|
name: "OSPF",
|
||||||
template: "ospf%d",
|
template: "ospf%d",
|
||||||
|
attr_class: EAP_OSPF,
|
||||||
init: ospf_init,
|
init: ospf_init,
|
||||||
dump: ospf_dump,
|
dump: ospf_dump,
|
||||||
start: ospf_start,
|
start: ospf_start,
|
||||||
shutdown: ospf_shutdown,
|
shutdown: ospf_shutdown,
|
||||||
get_route_info: ospf_get_route_info,
|
get_route_info: ospf_get_route_info,
|
||||||
|
get_attr: ospf_get_attr,
|
||||||
get_status: ospf_get_status
|
get_status: ospf_get_status
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
static int ospf_rte_same(struct rte *new, struct rte *old);
|
||||||
int ospf_import_control(struct proto *p, rte **new, ea_list **attrs,
|
int ospf_import_control(struct proto *p, rte **new, ea_list **attrs,
|
||||||
struct linpool *pool);
|
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);
|
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/hello.h"
|
||||||
#include "proto/ospf/packet.h"
|
#include "proto/ospf/packet.h"
|
||||||
#include "proto/ospf/iface.h"
|
#include "proto/ospf/iface.h"
|
||||||
|
|
|
@ -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);
|
flood_lsa(NULL,NULL,&ifa->nlsa->lsa,po,NULL,ifa->oa,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
static void *
|
||||||
originate_ext_lsa_body(net *n, rte *e, struct proto_ospf *po)
|
originate_ext_lsa_body(net *n, rte *e, struct proto_ospf *po, struct ea_list *attrs)
|
||||||
{
|
{
|
||||||
struct proto *p=&po->proto;
|
struct proto *p=&po->proto;
|
||||||
struct ospf_lsa_ext *ext;
|
struct ospf_lsa_ext *ext;
|
||||||
struct ospf_lsa_ext_tos *et;
|
struct ospf_lsa_ext_tos *et;
|
||||||
neighbor *nn;
|
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)+
|
ext=mb_alloc(p->pool,sizeof(struct ospf_lsa_ext)+
|
||||||
sizeof(struct ospf_lsa_ext_tos));
|
sizeof(struct ospf_lsa_ext_tos));
|
||||||
ext->netmask=ipa_mkmask(n->n.pxlen);
|
ext->netmask=ipa_mkmask(n->n.pxlen);
|
||||||
|
|
||||||
et=(struct ospf_lsa_ext_tos *)(ext+1);
|
et=(struct ospf_lsa_ext_tos *)(ext+1);
|
||||||
if(e->u.ospf.metric2!=0)
|
|
||||||
|
if(!m2)
|
||||||
{
|
{
|
||||||
et->etos=0;
|
et->etos=0;
|
||||||
et->metric=e->u.ospf.metric1;
|
et->metric=m1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
et->etos=1;
|
et->etos=0x80;
|
||||||
et->metric=e->u.ospf.metric2;
|
et->metric=m2;
|
||||||
}
|
}
|
||||||
et->padding=0;
|
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*/
|
if(1) et->fwaddr= ipa_from_u32(0); /* FIXME if e->attrs->iface is not in my AS*/
|
||||||
else et->fwaddr=e->attrs->gw;
|
else et->fwaddr=e->attrs->gw;
|
||||||
return ext;
|
return ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
struct ospf_lsa_header lsa;
|
||||||
u32 rtid=po->proto.cf->global->router_id;
|
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.type=LSA_T_EXT;
|
||||||
lsa.rt=rtid;
|
lsa.rt=rtid;
|
||||||
lsa.sn=LSA_INITSEQNO;
|
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)+
|
lsa.length=sizeof(struct ospf_lsa_ext)+sizeof(struct ospf_lsa_ext_tos)+
|
||||||
sizeof(struct ospf_lsa_header);
|
sizeof(struct ospf_lsa_header);
|
||||||
lsasum_calculate(&lsa,body,po);
|
lsasum_calculate(&lsa,body,po);
|
||||||
|
|
|
@ -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_rt_lsa(struct ospf_area *oa,struct proto_ospf *po);
|
||||||
void originate_net_lsa(struct ospf_iface *ifa,struct proto_ospf *po);
|
void originate_net_lsa(struct ospf_iface *ifa,struct proto_ospf *po);
|
||||||
int can_flush_lsa(struct ospf_area *oa);
|
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_ */
|
#endif /* _BIRD_OSPF_TOPOLOGY_H_ */
|
||||||
|
|
Loading…
Reference in a new issue