Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Quagga: Users

Re: Problem with conditional default-information originate in ospfd

 

 

Quagga users RSS feed   Index | Next | Previous | View Threaded


unik at compot

Jun 12, 2011, 10:44 AM

Post #1 of 2 (361 views)
Permalink
Re: Problem with conditional default-information originate in ospfd

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);
Attachments: signature.asc (0.19 KB)


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

Quagga users RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.