
ndenev at gmail
Nov 19, 2011, 4:35 PM
Post #2 of 2
(208 views)
Permalink
|
|
Re: Problem with conditional default-information originate in ospfd
[In reply to]
|
|
On Jun 12, 2011, at 8:44 PM, Unik wrote: > Hello. > > As a followup to my previous message, after some 2 days of research and > trying, I came up with a patch to do this: > > === cut === > > default-information originate always route-map SOME-MAP > > route-map SOME-MAP permit 10 > match ip address prefix-list PL-CHECK-HEALTH > > route-map SOME-MAP deny 20 > > === cut === > > It has several limitations in current form: > > 1. No work has been done for IPv6. > 2. Only prefix-list matching is supported for now. > > Patch is rather intrusive: > > 1. It moves struct prefix_list_entry definition from private .c file to > public .h file. > > 2. It adds new zserv message type (lookup in RIB by prefix). I tried to > use existing types, but to no avail (all existing lookups ignore eBGP > routes). > > 3. It adds new route-map object type (RMAP_OSPF_DEFAULT). Currently only > prefix list matching is implemented for this type. > > So, here is the patch (on top of 0.99.18), let the flames/review > commence. > > === === === > > diff -Naur quagga-0.99.18-orig/lib/plist.c quagga-0.99.18/lib/plist.c > --- quagga-0.99.18-orig/lib/plist.c 2011-03-21 12:43:52.000000000 +0300 > +++ quagga-0.99.18/lib/plist.c 2011-06-11 09:23:02.395467744 +0400 > @@ -30,26 +30,6 @@ > #include "stream.h" > #include "log.h" > > -/* Each prefix-list's entry. */ > -struct prefix_list_entry > -{ > - int seq; > - > - int le; > - int ge; > - > - enum prefix_list_type type; > - > - int any; > - struct prefix prefix; > - > - unsigned long refcnt; > - unsigned long hitcnt; > - > - struct prefix_list_entry *next; > - struct prefix_list_entry *prev; > -}; > - > /* List of struct prefix_list. */ > struct prefix_list_list > { > diff -Naur quagga-0.99.18-orig/lib/plist.h quagga-0.99.18/lib/plist.h > --- quagga-0.99.18-orig/lib/plist.h 2011-03-21 12:43:52.000000000 +0300 > +++ quagga-0.99.18/lib/plist.h 2011-06-11 09:22:28.572134635 +0400 > @@ -56,6 +56,26 @@ > struct prefix_list *prev; > }; > > +/* Each prefix-list's entry. */ > +struct prefix_list_entry > +{ > + int seq; > + > + int le; > + int ge; > + > + enum prefix_list_type type; > + > + int any; > + struct prefix prefix; > + > + unsigned long refcnt; > + unsigned long hitcnt; > + > + struct prefix_list_entry *next; > + struct prefix_list_entry *prev; > +}; > + > struct orf_prefix > { > u_int32_t seq; > diff -Naur quagga-0.99.18-orig/lib/routemap.h quagga-0.99.18/lib/routemap.h > --- quagga-0.99.18-orig/lib/routemap.h 2011-03-21 12:43:52.000000000 +0300 > +++ quagga-0.99.18/lib/routemap.h 2011-06-11 08:19:17.622159706 +0400 > @@ -46,7 +46,8 @@ > RMAP_OSPF, > RMAP_OSPF6, > RMAP_BGP, > - RMAP_ZEBRA > + RMAP_ZEBRA, > + RMAP_OSPF_DEFAULT > } route_map_object_t; > > typedef enum > diff -Naur quagga-0.99.18-orig/lib/zebra.h quagga-0.99.18/lib/zebra.h > --- quagga-0.99.18-orig/lib/zebra.h 2011-03-21 12:43:52.000000000 +0300 > +++ quagga-0.99.18/lib/zebra.h 2011-06-12 06:44:49.426606713 +0400 > @@ -421,7 +421,9 @@ > #define ZEBRA_ROUTER_ID_ADD 20 > #define ZEBRA_ROUTER_ID_DELETE 21 > #define ZEBRA_ROUTER_ID_UPDATE 22 > -#define ZEBRA_MESSAGE_MAX 23 > +#define ZEBRA_IPV4_RIB_LOOKUP 23 > +#define ZEBRA_IPV6_RIB_LOOKUP 24 > +#define ZEBRA_MESSAGE_MAX 25 > > /* Marker value used in new Zserv, in the byte location corresponding > * the command value in the old zserv header. To allow old and new > diff -Naur quagga-0.99.18-orig/ospfd/ospf_routemap.c quagga-0.99.18/ospfd/ospf_routemap.c > --- quagga-0.99.18-orig/ospfd/ospf_routemap.c 2011-03-21 12:43:52.000000000 +0300 > +++ quagga-0.99.18/ospfd/ospf_routemap.c 2011-06-12 08:04:41.326574811 +0400 > @@ -331,6 +331,35 @@ > route_match_ip_address_free > }; > > +/* as following, but in default-originate route-map context */ > +static route_map_result_t > +route_default_match_ip_address_prefix_list (void *rule, struct prefix *prefix, > + route_map_object_t type, void *object) > +{ > + struct prefix_list *plist; > + struct prefix_list_entry *pentry; > + > + if (type == RMAP_OSPF_DEFAULT) > + { > + plist = prefix_list_lookup (AFI_IP, (char *) rule); > + if (plist == NULL) > + return RMAP_NOMATCH; > + > + if (plist->count == 0) > + return RMAP_MATCH; > + for (pentry = plist->head; pentry; pentry = pentry->next) > + { > + pentry->refcnt++; > + if (ospf_zebra_lookup_query (&(pentry->prefix.u.prefix4))) > + { > + pentry->hitcnt++; > + return RMAP_MATCH; > + } > + } > + } > + return RMAP_NOMATCH; > +} > + > /* `match ip address prefix-list PREFIX_LIST' */ > static route_map_result_t > route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, > @@ -347,6 +376,9 @@ > return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? > RMAP_NOMATCH : RMAP_MATCH); > } > + else if (type == RMAP_OSPF_DEFAULT) > + return route_default_match_ip_address_prefix_list (rule, prefix, type, > + object); > return RMAP_NOMATCH; > } > > diff -Naur quagga-0.99.18-orig/ospfd/ospf_zebra.c quagga-0.99.18/ospfd/ospf_zebra.c > --- quagga-0.99.18-orig/ospfd/ospf_zebra.c 2011-03-21 12:43:52.000000000 +0300 > +++ quagga-0.99.18/ospfd/ospf_zebra.c 2011-06-12 08:03:58.646575097 +0400 > @@ -51,6 +51,7 @@ > > /* Zebra structure to hold current status. */ > struct zclient *zclient = NULL; > +struct zclient *zlookup = NULL; > > /* For registering threads. */ > extern struct thread_master *master; > @@ -473,6 +474,92 @@ > } > } > > +int > +ospf_zebra_lookup_read () > +{ > + struct stream *s; > + uint16_t length; > + u_char marker; > + u_char version; > + uint16_t command; > + int nbytes; > + struct in_addr raddr; > + uint32_t metric; > + u_char nexthop_num; > + > + zlog_info("ospf_zebra_lookup_read: phase 1"); > + > + s = zlookup->ibuf; > + stream_reset (s); > + > + nbytes = stream_read (s, zlookup->sock, 2); > + length = stream_getw (s); > + > + nbytes = stream_read (s, zlookup->sock, length - 2); > + marker = stream_getc (s); > + version = stream_getc (s); > + > + if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER) > + { > + zlog_err("%s: socket %d version mismatch, marker %d, version %d", > + __func__, zlookup->sock, marker, version); > + return 0; > + } > + > + command = stream_getw (s); > + > + raddr.s_addr = stream_get_ipv4 (s); > + metric = stream_getl (s); > + nexthop_num = stream_getc (s); > + > + if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) > + { > + zlog_debug("ospf_zebra_lookup_read: got %s", inet_ntoa(raddr)); > + zlog_debug("ospf_zebra_lookup_read: got metric %u", metric); > + zlog_debug("ospf_zebra_lookup_read: got nexthop_num %u", nexthop_num); > + } > + > + return ( (metric > 0) || (nexthop_num > 0) ? 1 : 0 ); > +} > + > +int > +ospf_zebra_lookup_query (struct prefix_ipv4 *p) > +{ > + int ret; > + struct stream *s; > + > + /* Check socket. */ > + if (zlookup->sock < 0) > + return 0; > + > + s = zlookup->obuf; > + stream_reset (s); > + zclient_create_header (s, ZEBRA_IPV4_RIB_LOOKUP); > + > + stream_putc (s, p->prefixlen); > + stream_put_in_addr (s, &p->prefix); > + > + stream_putw_at (s, 0, stream_get_endp (s)); > + > + ret = writen (zlookup->sock, s->data, stream_get_endp (s)); > + if (ret < 0) > + { > + zlog_err ("can't write to zlookup->sock"); > + close (zlookup->sock); > + zlookup->sock = -1; > + return 0; > + } > + if (ret == 0) > + { > + zlog_err ("zlookup->sock connection closed"); > + close (zlookup->sock); > + zlookup->sock = -1; > + return 0; > + } > + > + return ospf_zebra_lookup_read (); > +} > + > void > ospf_zebra_add_discard (struct prefix_ipv4 *p) > { > @@ -733,7 +820,9 @@ > int ret; > > ret = route_map_apply (ROUTEMAP (ospf, type), (struct prefix *) p, > - RMAP_OSPF, ei); > + (DEFAULT_ROUTE_TYPE (type) ? RMAP_OSPF_DEFAULT : > + RMAP_OSPF), > + ei); > > if (ret == RMAP_DENYMATCH) > { > @@ -1257,6 +1346,29 @@ > return 0; > } > > +/* Connect to zebra for nexthop lookup. */ > +static int > +zlookup_connect (struct thread *t) > +{ > + struct zclient *zlookup; > + > + zlookup = THREAD_ARG (t); > + zlookup->t_connect = NULL; > + > + if (zlookup->sock != -1) > + return 0; > + > +#ifdef HAVE_TCP_ZEBRA > + zlookup->sock = zclient_socket (); > +#else > + zlookup->sock = zclient_socket_un (ZEBRA_SERV_PATH); > +#endif /* HAVE_TCP_ZEBRA */ > + if (zlookup->sock < 0) > + return -1; > + > + return 0; > +} > + > void > ospf_zebra_init () > { > @@ -1273,6 +1385,10 @@ > zclient->ipv4_route_add = ospf_zebra_read_ipv4; > zclient->ipv4_route_delete = ospf_zebra_read_ipv4; > > + zlookup = zclient_new (); > + zlookup->sock = -1; > + zlookup->t_connect = thread_add_event (master, zlookup_connect, zlookup, 0); > + > access_list_add_hook (ospf_filter_update); > access_list_delete_hook (ospf_filter_update); > prefix_list_add_hook (ospf_prefix_list_update); > diff -Naur quagga-0.99.18-orig/ospfd/ospf_zebra.h quagga-0.99.18/ospfd/ospf_zebra.h > --- quagga-0.99.18-orig/ospfd/ospf_zebra.h 2011-03-21 12:43:52.000000000 +0300 > +++ quagga-0.99.18/ospfd/ospf_zebra.h 2011-06-12 07:28:16.123256463 +0400 > @@ -47,6 +47,8 @@ > extern void ospf_zebra_add (struct prefix_ipv4 *, struct ospf_route *); > extern void ospf_zebra_delete (struct prefix_ipv4 *, struct ospf_route *); > > +extern int ospf_zebra_lookup_query (struct prefix_ipv4 *); > + > extern void ospf_zebra_add_discard (struct prefix_ipv4 *); > extern void ospf_zebra_delete_discard (struct prefix_ipv4 *); > > diff -Naur quagga-0.99.18-orig/zebra/rib.h quagga-0.99.18/zebra/rib.h > --- quagga-0.99.18-orig/zebra/rib.h 2011-03-21 12:43:52.000000000 +0300 > +++ quagga-0.99.18/zebra/rib.h 2011-06-12 07:08:01.483264114 +0400 > @@ -260,6 +260,7 @@ > extern struct rib *rib_match_ipv4 (struct in_addr); > > extern struct rib *rib_lookup_ipv4 (struct prefix_ipv4 *); > +extern struct rib *rib_lookup_any_ipv4 (struct prefix_ipv4 *); > > extern void rib_update (void); > extern void rib_weed_tables (void); > @@ -286,6 +287,7 @@ > struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id); > > extern struct rib *rib_lookup_ipv6 (struct in6_addr *); > +extern struct rib *rib_lookup_any_ipv6 (struct in6_addr *); > > extern struct rib *rib_match_ipv6 (struct in6_addr *); > > diff -Naur quagga-0.99.18-orig/zebra/zebra_rib.c quagga-0.99.18/zebra/zebra_rib.c > --- quagga-0.99.18-orig/zebra/zebra_rib.c 2011-03-21 12:43:52.000000000 +0300 > +++ quagga-0.99.18/zebra/zebra_rib.c 2011-06-12 07:11:17.469929471 +0400 > @@ -616,6 +616,52 @@ > } > > /* > + * Same as rib_lookup_ipv4, except doesn't care if route is eBGP or not. > + */ > +struct rib * > +rib_lookup_any_ipv4 (struct prefix_ipv4 *p) > +{ > + struct route_table *table; > + struct route_node *rn; > + struct rib *match; > + struct nexthop *nexthop; > + > + /* Lookup table. */ > + table = vrf_table (AFI_IP, SAFI_UNICAST, 0); > + if (! table) > + return 0; > + > + rn = route_node_lookup (table, (struct prefix *) p); > + > + /* No route for this prefix. */ > + if (! rn) > + return NULL; > + > + /* Unlock node. */ > + route_unlock_node (rn); > + > + for (match = rn->info; match; match = match->next) > + { > + if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) > + continue; > + if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) > + break; > + } > + > + if (! match) > + return NULL; > + > + if (match->type == ZEBRA_ROUTE_CONNECT) > + return match; > + > + for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next) > + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) > + return match; > + > + return NULL; > +} > + > +/* > * This clone function, unlike its original rib_lookup_ipv4(), checks > * if specified IPv4 route record (prefix/mask -> gate) exists in > * the whole RIB and has ZEBRA_FLAG_SELECTED set. > diff -Naur quagga-0.99.18-orig/zebra/zserv.c quagga-0.99.18/zebra/zserv.c > --- quagga-0.99.18-orig/zebra/zserv.c 2011-03-21 12:43:52.000000000 +0300 > +++ quagga-0.99.18/zebra/zserv.c 2011-06-12 07:26:57.903256548 +0400 > @@ -596,6 +596,64 @@ > } > > static int > +zsend_ipv4_rib_lookup (struct zserv *client, struct prefix_ipv4 *p) > +{ > + struct stream *s; > + struct rib *rib; > + unsigned long nump; > + u_char num; > + struct nexthop *nexthop; > + > + /* Lookup nexthop. */ > + rib = rib_lookup_any_ipv4 (p); > + > + /* Get output stream. */ > + s = client->obuf; > + stream_reset (s); > + > + /* Fill in result. */ > + zserv_create_header (s, ZEBRA_IPV4_RIB_LOOKUP); > + stream_put_in_addr (s, &p->prefix); > + > + if (rib) > + { > + stream_putl (s, rib->metric); > + num = 0; > + nump = stream_get_endp(s); > + stream_putc (s, 0); > + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) > + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) > + { > + stream_putc (s, nexthop->type); > + switch (nexthop->type) > + { > + case ZEBRA_NEXTHOP_IPV4: > + stream_put_in_addr (s, &nexthop->gate.ipv4); > + break; > + case ZEBRA_NEXTHOP_IFINDEX: > + case ZEBRA_NEXTHOP_IFNAME: > + stream_putl (s, nexthop->ifindex); > + break; > + default: > + /* do nothing */ > + break; > + } > + num++; > + } > + stream_putc_at (s, nump, num); > + } > + else > + { > + stream_putl (s, 0); > + stream_putc (s, 0); > + } > + > + stream_putw_at (s, 0, stream_get_endp (s)); > + > + return zebra_server_send_message(client); > +} > + > +static int > zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p) > { > struct stream *s; > @@ -881,6 +939,19 @@ > return 0; > } > > +/* Simple RIB lookup for IPv4. */ > +static int > +zread_ipv4_rib_lookup (struct zserv *client, u_short length) > +{ > + struct prefix_ipv4 p; > + > + p.family = AF_INET; > + p.prefixlen = stream_getc (client->ibuf); > + p.prefix.s_addr = stream_get_ipv4 (client->ibuf); > + > + return zsend_ipv4_rib_lookup (client, &p); > +} > + > /* Nexthop lookup for IPv4. */ > static int > zread_ipv4_nexthop_lookup (struct zserv *client, u_short length) > @@ -1275,6 +1346,9 @@ > case ZEBRA_IPV4_NEXTHOP_LOOKUP: > zread_ipv4_nexthop_lookup (client, length); > break; > + case ZEBRA_IPV4_RIB_LOOKUP: > + zread_ipv4_rib_lookup (client, length); > + break; > #ifdef HAVE_IPV6 > case ZEBRA_IPV6_NEXTHOP_LOOKUP: > zread_ipv6_nexthop_lookup (client, length); > > _______________________________________________ > Quagga-users mailing list > Quagga-users [at] lists > http://lists.quagga.net/mailman/listinfo/quagga-users I'm having exactly the same problem, and I'm wondering why this is not yet included in the quagga source :) I'll give this patch a try in the next few days. _______________________________________________ Quagga-users mailing list Quagga-users [at] lists http://lists.quagga.net/mailman/listinfo/quagga-users
|