diff options
author | sem <sem@FreeBSD.org> | 2007-08-28 18:48:38 +0800 |
---|---|---|
committer | sem <sem@FreeBSD.org> | 2007-08-28 18:48:38 +0800 |
commit | f57e8739b083c6fcd0cb2a88edef69cfbabba112 (patch) | |
tree | ea4f40cba48bd8702fbcb80d2b62c17b0f49fbbd /net/quagga | |
parent | f50e668d31bae4c9b8f5b62c5709b850d414cdfe (diff) | |
download | freebsd-ports-gnome-f57e8739b083c6fcd0cb2a88edef69cfbabba112.tar.gz freebsd-ports-gnome-f57e8739b083c6fcd0cb2a88edef69cfbabba112.tar.zst freebsd-ports-gnome-f57e8739b083c6fcd0cb2a88edef69cfbabba112.zip |
- Integrate patches from quagga CVS.
They fix a few problems with inconsistences routes between
quagga and kernel route tables, loss MTU, assert in route-map code, etc.
Submitted by: Yandex company
Approved by: maintainer
Diffstat (limited to 'net/quagga')
-rw-r--r-- | net/quagga/Makefile | 1 | ||||
-rw-r--r-- | net/quagga/files/patch-cvs-1-bgpd-rm-assert | 210 | ||||
-rw-r--r-- | net/quagga/files/patch-cvs-2-ribcode | 46 | ||||
-rw-r--r-- | net/quagga/files/patch-cvs-3-ribdebug | 642 | ||||
-rw-r--r-- | net/quagga/files/patch-cvs-4-nexthop_active_update | 47 | ||||
-rw-r--r-- | net/quagga/files/patch-cvs-5-sendbuffer | 294 | ||||
-rw-r--r-- | net/quagga/files/patch-cvs-6-RTF_DONE | 20 | ||||
-rw-r--r-- | net/quagga/files/patch-cvs-7-ifm_read | 18 |
8 files changed, 1278 insertions, 0 deletions
diff --git a/net/quagga/Makefile b/net/quagga/Makefile index 68c365d4e556..92810dba5922 100644 --- a/net/quagga/Makefile +++ b/net/quagga/Makefile @@ -7,6 +7,7 @@ PORTNAME= quagga PORTVERSION= 0.99.8 +PORTREVISION= 1 CATEGORIES= net ipv6 MASTER_SITES= http://quagga.net/download/ \ http://www.ru.quagga.net/download/ \ diff --git a/net/quagga/files/patch-cvs-1-bgpd-rm-assert b/net/quagga/files/patch-cvs-1-bgpd-rm-assert new file mode 100644 index 000000000000..979572948340 --- /dev/null +++ b/net/quagga/files/patch-cvs-1-bgpd-rm-assert @@ -0,0 +1,210 @@ +--- bgpd/ChangeLog.orig 23 Aug 2007 23:22:02 -0000 1.140 ++++ bgpd/ChangeLog 27 Aug 2007 11:48:47 -0000 +@@ -1,3 +1,24 @@ ++2007-08-27 Paul Jakma <paul.jakma@sun.com> ++ ++ * bgp_route.c: (bgp_announce_check) Fix bug #398, slight ++ modification of Vladimir Ivanov's suggested fix - to keep ++ memory alloc conditional. ++ (bgp_process_announce_selected) Don't take struct attr as ++ argument, none of the callers need it and it needlessly ++ distances allocation from use. ++ Free the extended attr, the attr itself is on the stack. ++ Fix bad indentation. ++ * bgp_attr.c: (bgp_packet_attribute) Remove incorrect assert, ++ and adjust conditional to test attr->extra, diagnosis by ++ Vladimir Ivanov in bug #398. ++ ++2007-08-27 Vladimir Ivanov <wawa@yandex-team.ru> ++ ++ * bgp_route.c: (bgp_announce_check_rsclient) copy of ++ ri->attr is no longer deep enough, due to addition of ++ attr->extra. It should use bgp_attr_dup, as ++ bgp_announce_check() does. ++ + 2007-08-23 Paul Jakma <paul.jakma@sun.com> + + * bgp_regex.c: (bgp_regcomp) Pass NOSUB flag to regcomp to +--- bgpd/bgp_attr.c.orig 6 Aug 2007 15:24:51 -0000 1.22 ++++ bgpd/bgp_attr.c 27 Aug 2007 11:48:47 -0000 +@@ -1673,8 +1673,6 @@ bgp_packet_attribute (struct bgp *bgp, s + && from + && peer_sort (from) == BGP_PEER_IBGP) + { +- assert (attr->extra); +- + /* Originator ID. */ + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); + stream_putc (s, BGP_ATTR_ORIGINATOR_ID); +@@ -1689,7 +1687,7 @@ bgp_packet_attribute (struct bgp *bgp, s + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); + stream_putc (s, BGP_ATTR_CLUSTER_LIST); + +- if (attr->extra->cluster) ++ if (attr->extra && attr->extra->cluster) + { + stream_putc (s, attr->extra->cluster->length + 4); + /* If this peer configuration's parent BGP has cluster_id. */ +--- bgpd/bgp_route.c.orig 6 Aug 2007 15:24:51 -0000 1.63 ++++ bgpd/bgp_route.c 27 Aug 2007 11:48:48 -0000 +@@ -1045,20 +1045,18 @@ bgp_announce_check (struct bgp_info *ri, + || (ri->extra && ri->extra->suppress) ) + { + struct bgp_info info; +- struct attr dummy_attr; ++ struct attr dummy_attr = { 0 }; + + info.peer = peer; + info.attr = attr; +- + + /* The route reflector is not allowed to modify the attributes + of the reflected IBGP routes. */ + if (peer_sort (from) == BGP_PEER_IBGP + && peer_sort (peer) == BGP_PEER_IBGP) + { +- dummy_attr.extra = NULL; + bgp_attr_dup (&dummy_attr, attr); +- info.attr = &dummy_attr; ++ info.attr = &dummy_attr; + } + + SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT); +@@ -1070,7 +1068,8 @@ bgp_announce_check (struct bgp_info *ri, + + peer->rmap_type = 0; + +- bgp_attr_extra_free (&dummy_attr); ++ if (dummy_attr.extra) ++ bgp_attr_extra_free (&dummy_attr); + + if (ret == RMAP_DENYMATCH) + { +@@ -1173,7 +1172,7 @@ bgp_announce_check_rsclient (struct bgp_ + #endif /* BGP_SEND_ASPATH_CHECK */ + + /* For modify attribute, copy it to temporary structure. */ +- *attr = *ri->attr; ++ bgp_attr_dup (attr, ri->attr); + + /* next-hop-set */ + if ((p->family == AF_INET && attr->nexthop.s_addr == 0) +@@ -1375,21 +1374,22 @@ bgp_best_selection (struct bgp *bgp, str + + static int + bgp_process_announce_selected (struct peer *peer, struct bgp_info *selected, +- struct bgp_node *rn, struct attr *attr, afi_t afi, safi_t safi) +- { ++ struct bgp_node *rn, afi_t afi, safi_t safi) ++{ + struct prefix *p; ++ struct attr attr = { 0 }; + + p = &rn->p; + +- /* Announce route to Established peer. */ +- if (peer->status != Established) ++ /* Announce route to Established peer. */ ++ if (peer->status != Established) + return 0; + +- /* Address family configuration check. */ +- if (! peer->afc_nego[afi][safi]) ++ /* Address family configuration check. */ ++ if (! peer->afc_nego[afi][safi]) + return 0; + +- /* First update is deferred until ORF or ROUTE-REFRESH is received */ ++ /* First update is deferred until ORF or ROUTE-REFRESH is received */ + if (CHECK_FLAG (peer->af_sflags[afi][safi], + PEER_STATUS_ORF_WAIT_REFRESH)) + return 0; +@@ -1399,21 +1399,24 @@ bgp_process_announce_selected (struct pe + case BGP_TABLE_MAIN: + /* Announcement to peer->conf. If the route is filtered, + withdraw it. */ +- if (selected && bgp_announce_check (selected, peer, p, attr, afi, safi)) +- bgp_adj_out_set (rn, peer, p, attr, afi, safi, selected); ++ if (selected && bgp_announce_check (selected, peer, p, &attr, afi, safi)) ++ bgp_adj_out_set (rn, peer, p, &attr, afi, safi, selected); + else + bgp_adj_out_unset (rn, peer, p, afi, safi); + break; + case BGP_TABLE_RSCLIENT: + /* Announcement to peer->conf. If the route is filtered, + withdraw it. */ +- if (selected && bgp_announce_check_rsclient +- (selected, peer, p, attr, afi, safi)) +- bgp_adj_out_set (rn, peer, p, attr, afi, safi, selected); +- else +- bgp_adj_out_unset (rn, peer, p, afi, safi); ++ if (selected && ++ bgp_announce_check_rsclient (selected, peer, p, &attr, afi, safi)) ++ bgp_adj_out_set (rn, peer, p, &attr, afi, safi, selected); ++ else ++ bgp_adj_out_unset (rn, peer, p, afi, safi); + break; + } ++ ++ bgp_attr_extra_free (&attr); ++ + return 0; + } + +@@ -1463,8 +1466,7 @@ bgp_process_rsclient (struct work_queue + bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED); + } + +- bgp_process_announce_selected (rsclient, new_select, rn, &attr, +- afi, safi); ++ bgp_process_announce_selected (rsclient, new_select, rn, afi, safi); + } + } + else +@@ -1476,8 +1478,7 @@ bgp_process_rsclient (struct work_queue + bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED); + bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED); + } +- bgp_process_announce_selected (rsclient, new_select, rn, +- &attr, afi, safi); ++ bgp_process_announce_selected (rsclient, new_select, rn, afi, safi); + } + + if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED)) +@@ -1503,9 +1504,6 @@ bgp_process_main (struct work_queue *wq, + struct bgp_info_pair old_and_new; + struct listnode *node, *nnode; + struct peer *peer; +- struct attr attr; +- +- memset (&attr, 0, sizeof (struct attr)); + + /* Best path selection. */ + bgp_best_selection (bgp, rn, &old_and_new); +@@ -1537,7 +1535,7 @@ bgp_process_main (struct work_queue *wq, + /* Check each BGP peer. */ + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + { +- bgp_process_announce_selected (peer, new_select, rn, &attr, afi, safi); ++ bgp_process_announce_selected (peer, new_select, rn, afi, safi); + } + + /* FIB update. */ +@@ -1562,8 +1560,6 @@ bgp_process_main (struct work_queue *wq, + if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED)) + bgp_info_reap (rn, old_select); + +- bgp_attr_extra_free (&attr); +- + UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); + return WQ_SUCCESS; + } +@@ -6214,7 +6210,7 @@ bgp_show_table (struct vty *vty, struct + { + struct route_map *rmap = output_arg; + struct bgp_info binfo; +- struct attr dummy_attr; ++ struct attr dummy_attr = { 0 }; + int ret; + + bgp_attr_dup (&dummy_attr, ri->attr); diff --git a/net/quagga/files/patch-cvs-2-ribcode b/net/quagga/files/patch-cvs-2-ribcode new file mode 100644 index 000000000000..bdf05a47561b --- /dev/null +++ b/net/quagga/files/patch-cvs-2-ribcode @@ -0,0 +1,46 @@ +--- zebra/rt_socket.c.orig 2007-05-10 00:59:35.000000000 +0400 ++++ zebra/rt_socket.c 2007-07-31 15:58:18.000000000 +0400 +@@ -99,9 +99,7 @@ + if ((cmd == RTM_ADD + && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + || (cmd == RTM_DELETE +-#if 0 + && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) +-#endif + )) + { + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) +@@ -138,9 +136,6 @@ + } + } + +- if (cmd == RTM_ADD) +- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); +- + if (gate && p->prefixlen == 32) + mask = NULL; + else +@@ -152,7 +147,6 @@ + #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ + mask = &sin_mask; + } +- } + + error = rtm_write (cmd, + (union sockunion *)&sin_dest, +@@ -169,8 +163,13 @@ + nexthop_num, error); + } + #endif +- +- nexthop_num++; ++ if (error == 0) ++ { ++ nexthop_num++; ++ if (cmd == RTM_ADD) ++ SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); ++ } ++ } + } + + /* If there is no useful nexthop then return. */ diff --git a/net/quagga/files/patch-cvs-3-ribdebug b/net/quagga/files/patch-cvs-3-ribdebug new file mode 100644 index 000000000000..a6b80f9f3cfd --- /dev/null +++ b/net/quagga/files/patch-cvs-3-ribdebug @@ -0,0 +1,642 @@ +--- lib/zebra.h.orig 2007-06-14 14:02:13.000000000 +0400 ++++ lib/zebra.h 2007-08-08 12:19:21.000000000 +0400 +@@ -454,10 +454,12 @@ + #define ZEBRA_FAMILY_MAX 3 + + /* Error codes of zebra. */ ++#define ZEBRA_ERR_NOERROR 0 + #define ZEBRA_ERR_RTEXIST -1 + #define ZEBRA_ERR_RTUNREACH -2 + #define ZEBRA_ERR_EPERM -3 + #define ZEBRA_ERR_RTNOEXIST -4 ++#define ZEBRA_ERR_KERNEL -5 + + /* Zebra message flags */ + #define ZEBRA_FLAG_INTERNAL 0x01 +--- zebra/kernel_socket.c.orig 2007-07-27 20:40:57.000000000 +0400 ++++ zebra/kernel_socket.c 2007-08-08 14:52:36.000000000 +0400 +@@ -160,6 +160,7 @@ + #endif /* RTM_IFANNOUNCE */ + {0, NULL} + }; ++int rtm_type_str_max = sizeof (rtm_type_str) / sizeof (struct message) - 1; + + struct message rtm_flag_str[] = + { +@@ -737,14 +738,12 @@ + + zebra_flags = 0; + +- /* Discard self send message. */ +- if (rtm->rtm_type != RTM_GET +- && (rtm->rtm_pid == pid || rtm->rtm_pid == old_pid)) +- return; +- + /* Read destination and netmask and gateway from rtm message + structure. */ + flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen); ++ if (IS_ZEBRA_DEBUG_KERNEL) ++ zlog_debug ("%s: got rtm of type %d (%s)", __func__, rtm->rtm_type, ++ LOOKUP (rtm_type_str, rtm->rtm_type)); + + #ifdef RTF_CLONED /*bsdi, netbsd 1.6*/ + if (flags & RTF_CLONED) +@@ -786,6 +785,79 @@ + else + p.prefixlen = ip_masklen (mask.sin.sin_addr); + ++ /* Catch self originated messages and match them against our current RIB. ++ * At the same time, ignore unconfirmed messages, they should be tracked ++ * by rtm_write() and kernel_rtm_ipv4(). ++ */ ++ if (rtm->rtm_type != RTM_GET ++ && (rtm->rtm_pid == pid || rtm->rtm_pid == old_pid)) ++ { ++ char buf[INET_ADDRSTRLEN], gate_buf[INET_ADDRSTRLEN]; ++ int ret; ++ if (!(flags & RTF_DONE)) ++ return; ++ if (! IS_ZEBRA_DEBUG_RIB) ++ return; ++ ret = rib_lookup_ipv4_route (&p, &gate); ++ inet_ntop (AF_INET, &p.prefix, buf, INET_ADDRSTRLEN); ++ switch (rtm->rtm_type) ++ { ++ case RTM_ADD: ++ case RTM_GET: ++ case RTM_CHANGE: ++ /* The kernel notifies us about a new route in FIB created by us. ++ Do we have a correspondent entry in our RIB? */ ++ switch (ret) ++ { ++ case ZEBRA_RIB_NOTFOUND: ++ zlog_debug ("%s: %s %s/%d: desync: RR isn't yet in RIB, while already in FIB", ++ __func__, LOOKUP (rtm_type_str, rtm->rtm_type), buf, p.prefixlen); ++ break; ++ case ZEBRA_RIB_FOUND_CONNECTED: ++ case ZEBRA_RIB_FOUND_NOGATE: ++ inet_ntop (AF_INET, &gate.sin.sin_addr, gate_buf, INET_ADDRSTRLEN); ++ zlog_debug ("%s: %s %s/%d: desync: RR is in RIB, but gate differs (ours is %s)", ++ __func__, LOOKUP (rtm_type_str, rtm->rtm_type), buf, p.prefixlen, gate_buf); ++ break; ++ case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR */ ++ zlog_debug ("%s: %s %s/%d: done Ok", ++ __func__, LOOKUP (rtm_type_str, rtm->rtm_type), buf, p.prefixlen); ++ rib_lookup_and_dump (&p); ++ return; ++ break; ++ } ++ break; ++ case RTM_DELETE: ++ /* The kernel notifies us about a route deleted by us. Do we still ++ have it in the RIB? Do we have anything instead? */ ++ switch (ret) ++ { ++ case ZEBRA_RIB_FOUND_EXACT: ++ zlog_debug ("%s: %s %s/%d: desync: RR is still in RIB, while already not in FIB", ++ __func__, LOOKUP (rtm_type_str, rtm->rtm_type), buf, p.prefixlen); ++ rib_lookup_and_dump (&p); ++ break; ++ case ZEBRA_RIB_FOUND_CONNECTED: ++ case ZEBRA_RIB_FOUND_NOGATE: ++ zlog_debug ("%s: %s %s/%d: desync: RR is still in RIB, plus gate differs", ++ __func__, LOOKUP (rtm_type_str, rtm->rtm_type), buf, p.prefixlen); ++ rib_lookup_and_dump (&p); ++ break; ++ case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */ ++ zlog_debug ("%s: %s %s/%d: done Ok", ++ __func__, LOOKUP (rtm_type_str, rtm->rtm_type), buf, p.prefixlen); ++ rib_lookup_and_dump (&p); ++ return; ++ break; ++ } ++ break; ++ default: ++ zlog_debug ("%s: %s/%d: warning: loopback RTM of type %s received", ++ __func__, buf, p.prefixlen, LOOKUP (rtm_type_str, rtm->rtm_type)); ++ } ++ return; ++ } ++ + /* Change, delete the old prefix, we have no further information + * to specify the route really + */ +@@ -903,7 +975,13 @@ + { + if (!ifp) + { +- zlog_warn ("no gateway found for interface index %d", index); ++ char dest_buf[INET_ADDRSTRLEN] = "NULL", mask_buf[INET_ADDRSTRLEN] = "255.255.255.255"; ++ if (dest) ++ inet_ntop (AF_INET, &dest->sin.sin_addr, dest_buf, INET_ADDRSTRLEN); ++ if (mask) ++ inet_ntop (AF_INET, &mask->sin.sin_addr, mask_buf, INET_ADDRSTRLEN); ++ zlog_warn ("%s: %s/%s: gate == NULL and no gateway found for ifindex %d", ++ __func__, dest_buf, mask_buf, index); + return -1; + } + gate = (union sockunion *) & ifp->sdl; +@@ -959,11 +1037,13 @@ + return ZEBRA_ERR_RTEXIST; + if (errno == ENETUNREACH) + return ZEBRA_ERR_RTUNREACH; ++ if (errno == ESRCH) ++ return ZEBRA_ERR_RTNOEXIST; + +- zlog_warn ("write : %s (%d)", safe_strerror (errno), errno); +- return -1; ++ zlog_warn ("%s: write : %s (%d)", __func__, safe_strerror (errno), errno); ++ return ZEBRA_ERR_KERNEL; + } +- return 0; ++ return ZEBRA_ERR_NOERROR; + } + + +@@ -974,17 +1054,7 @@ + static void + rtmsg_debug (struct rt_msghdr *rtm) + { +- const char *type = "Unknown"; +- struct message *mes; +- +- for (mes = rtm_type_str; mes->str; mes++) +- if (mes->key == rtm->rtm_type) +- { +- type = mes->str; +- break; +- } +- +- zlog_debug ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, type); ++ zlog_debug ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, LOOKUP (rtm_type_str, rtm->rtm_type)); + rtm_flag_dump (rtm->rtm_flags); + zlog_debug ("Kernel: message seq %d", rtm->rtm_seq); + zlog_debug ("Kernel: pid %d, rtm_addrs 0x%x", rtm->rtm_pid, rtm->rtm_addrs); +--- zebra/kernel_socket.h.orig 2005-11-24 18:10:48.000000000 +0300 ++++ zebra/kernel_socket.h 2007-08-08 12:19:21.000000000 +0400 +@@ -28,5 +28,7 @@ + extern int ifm_read (struct if_msghdr *); + extern int rtm_write (int, union sockunion *, union sockunion *, + union sockunion *, unsigned int, int, int); ++extern struct message rtm_type_str[]; ++extern int rtm_type_str_max; + + #endif /* __ZEBRA_KERNEL_SOCKET_H */ +--- zebra/rib.h.orig 2007-05-02 19:28:33.000000000 +0400 ++++ zebra/rib.h 2007-08-08 12:19:21.000000000 +0400 +@@ -211,6 +211,15 @@ + extern struct nexthop *nexthop_blackhole_add (struct rib *); + extern struct nexthop *nexthop_ipv4_add (struct rib *, struct in_addr *, + struct in_addr *); ++extern void rib_lookup_and_dump (struct prefix_ipv4 *); ++extern void rib_dump (const char *, const struct prefix_ipv4 *, const struct rib *); ++extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *); ++#define ZEBRA_RIB_LOOKUP_ERROR -1 ++#define ZEBRA_RIB_FOUND_EXACT 0 ++#define ZEBRA_RIB_FOUND_NOGATE 1 ++#define ZEBRA_RIB_FOUND_CONNECTED 2 ++#define ZEBRA_RIB_NOTFOUND 3 ++ + #ifdef HAVE_IPV6 + extern struct nexthop *nexthop_ipv6_add (struct rib *, struct in6_addr *); + #endif /* HAVE_IPV6 */ +--- zebra/rt_socket.c.orig 2007-08-08 12:08:40.000000000 +0400 ++++ zebra/rt_socket.c 2007-08-08 12:41:01.000000000 +0400 +@@ -32,6 +32,7 @@ + #include "zebra/debug.h" + #include "zebra/rib.h" + #include "zebra/rt.h" ++#include "zebra/kernel_socket.h" + + extern struct zebra_privs_t zserv_privs; + +@@ -75,7 +76,10 @@ + unsigned int ifindex = 0; + int gate = 0; + int error; ++ char prefix_buf[INET_ADDRSTRLEN]; + ++ if (IS_ZEBRA_DEBUG_RIB) ++ inet_ntop (AF_INET, &p->u.prefix, prefix_buf, INET_ADDRSTRLEN); + memset (&sin_dest, 0, sizeof (struct sockaddr_in)); + sin_dest.sin_family = AF_INET; + #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN +@@ -95,6 +99,7 @@ + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + { + gate = 0; ++ char gate_buf[INET_ADDRSTRLEN] = "NULL"; + + if ((cmd == RTM_ADD + && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) +@@ -156,29 +161,61 @@ + rib->flags, + rib->metric); + +-#if 0 +- if (error) +- { +- zlog_info ("kernel_rtm_ipv4(): nexthop %d add error=%d.", +- nexthop_num, error); +- } +-#endif +- if (error == 0) +- { +- nexthop_num++; +- if (cmd == RTM_ADD) +- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); +- } +- } +- } +- +- /* If there is no useful nexthop then return. */ +- if (nexthop_num == 0) +- { +- if (IS_ZEBRA_DEBUG_KERNEL) +- zlog_debug ("kernel_rtm_ipv4(): No useful nexthop."); +- return 0; +- } ++ if (IS_ZEBRA_DEBUG_RIB) ++ { ++ if (!gate) ++ { ++ zlog_debug ("%s: %s/%d: attention! gate not found for rib %p", ++ __func__, prefix_buf, p->prefixlen, rib); ++ rib_dump (__func__, (struct prefix_ipv4 *)p, rib); ++ } ++ else ++ inet_ntop (AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN); ++ } ++ ++ switch (error) ++ { ++ /* We only flag nexthops as being in FIB if rtm_write() did its work. */ ++ case ZEBRA_ERR_NOERROR: ++ nexthop_num++; ++ if (IS_ZEBRA_DEBUG_RIB) ++ zlog_debug ("%s: %s/%d: successfully did NH %s", ++ __func__, prefix_buf, p->prefixlen, gate_buf); ++ if (cmd == RTM_ADD) ++ SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); ++ break; ++ ++ /* The only valid case for this error is kernel's failure to install ++ * a multipath route, which is common for FreeBSD. This should be ++ * ignored silently, but logged as an error otherwise. ++ */ ++ case ZEBRA_ERR_RTEXIST: ++ if (cmd != RTM_ADD) ++ zlog_err ("%s: rtm_write() returned %d for command %d", ++ __func__, error, cmd); ++ continue; ++ break; ++ ++ /* Given that our NEXTHOP_FLAG_FIB matches real kernel FIB, it isn't ++ * normal to get any other messages in ANY case. ++ */ ++ case ZEBRA_ERR_RTNOEXIST: ++ case ZEBRA_ERR_RTUNREACH: ++ default: ++ zlog_err ("%s: %s/%d: rtm_write() unexpectedly returned %d for command %s", ++ __func__, prefix_buf, p->prefixlen, error, LOOKUP (rtm_type_str, cmd)); ++ break; ++ } ++ } /* if (cmd and flags make sense) */ ++ else ++ if (IS_ZEBRA_DEBUG_RIB) ++ zlog_debug ("%s: odd command %s for flags %d", ++ __func__, LOOKUP (rtm_type_str, cmd), nexthop->flags); ++ } /* for (nexthop = ... */ ++ ++ /* If there was no useful nexthop, then complain. */ ++ if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL) ++ zlog_debug ("%s: No useful nexthops were found in RIB entry %p", __func__, rib); + + return 0; /*XXX*/ + } +--- zebra/zebra_rib.c.orig 2007-06-25 14:17:53.000000000 +0400 ++++ zebra/zebra_rib.c 2007-08-08 12:30:23.000000000 +0400 +@@ -631,6 +631,82 @@ + 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. ++ * ++ * Return values: ++ * -1: error ++ * 0: exact match found ++ * 1: a match was found with a different gate ++ * 2: connected route found ++ * 3: no matches found ++ */ ++int ++rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) ++{ ++ 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 ZEBRA_RIB_LOOKUP_ERROR; ++ ++ /* Scan the RIB table for exactly matching RIB entry. */ ++ rn = route_node_lookup (table, (struct prefix *) p); ++ ++ /* No route for this prefix. */ ++ if (! rn) ++ return ZEBRA_RIB_NOTFOUND; ++ ++ /* Unlock node. */ ++ route_unlock_node (rn); ++ ++ /* Find out if a "selected" RR for the discovered RIB entry exists ever. */ ++ 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; ++ } ++ ++ /* None such found :( */ ++ if (!match) ++ return ZEBRA_RIB_NOTFOUND; ++ ++ if (match->type == ZEBRA_ROUTE_CONNECT) ++ return ZEBRA_RIB_FOUND_CONNECTED; ++ ++ /* Ok, we have a cood candidate, let's check it's nexthop list... */ ++ for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next) ++ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) ++ { ++ /* We are happy with either direct or recursive hexthop */ ++ if (nexthop->gate.ipv4.s_addr == qgate->sin.sin_addr.s_addr || ++ nexthop->rgate.ipv4.s_addr == qgate->sin.sin_addr.s_addr) ++ return ZEBRA_RIB_FOUND_EXACT; ++ else ++ { ++ if (IS_ZEBRA_DEBUG_RIB) ++ { ++ char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN]; ++ inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN); ++ inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN); ++ inet_ntop (AF_INET, &qgate->sin.sin_addr.s_addr, qgate_buf, INET_ADDRSTRLEN); ++ zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf); ++ } ++ return ZEBRA_RIB_FOUND_NOGATE; ++ } ++ } ++ ++ return ZEBRA_RIB_NOTFOUND; ++} ++ + #ifdef HAVE_IPV6 + struct rib * + rib_match_ipv6 (struct in6_addr *addr) +@@ -694,6 +770,16 @@ + #define RIB_SYSTEM_ROUTE(R) \ + ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) + ++/* This function verifies reachability of one given nexthop, which can be ++ * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored ++ * in nexthop->flags field. If the 4th parameter, 'set', is non-zero, ++ * nexthop->ifindex will be updated appropriately as well. ++ * An existing route map can turn (otherwise active) nexthop into inactive, but ++ * not vice versa. ++ * ++ * The return value is the final value of 'ACTIVE' flag. ++ */ ++ + static int + nexthop_active_check (struct route_node *rn, struct rib *rib, + struct nexthop *nexthop, int set) +@@ -839,6 +925,7 @@ + #endif /* HAVE_IPV6 */ + } + ++ /* This condition is never met, if we are using rt_socket.c */ + if (ret < 0) + { + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) +@@ -860,6 +947,8 @@ + break; + #ifdef HAVE_IPV6 + case AF_INET6: ++ if (IS_ZEBRA_DEBUG_RIB) ++ zlog_debug ("%s: calling kernel_delete_ipv4 (%p, %p)", __func__, rn, rib); + ret = kernel_delete_ipv6 (&rn->p, rib); + break; + #endif /* HAVE_IPV6 */ +@@ -903,6 +992,9 @@ + + for (rib = rn->info; rib; rib = next) + { ++ /* The next pointer is saved, because current pointer ++ * may be passed to rib_unlink() in the middle of iteration. ++ */ + next = rib->next; + + /* Currently installed rib. */ +@@ -978,9 +1070,16 @@ + /* metric tie-breaks equal distance */ + if (rib->metric <= select->metric) + select = rib; +- } +- +- /* Same route is selected. */ ++ } /* for (rib = rn->info; rib; rib = next) */ ++ ++ /* After the cycle is finished, the following pointers will be set: ++ * select --- the winner RIB entry, if any was found, otherwise NULL ++ * fib --- the SELECTED RIB entry, if any, otherwise NULL ++ * del --- equal to fib, if fib is queued for deletion, NULL otherwise ++ * rib --- NULL ++ */ ++ ++ /* Same RIB entry is selected. Update FIB and finish. */ + if (select && select == fib) + { + if (IS_ZEBRA_DEBUG_RIB) +@@ -1019,7 +1118,10 @@ + goto end; + } + +- /* Uninstall old rib from forwarding table. */ ++ /* At this point we either haven't found the best RIB entry or it is ++ * different from what we currently intend to flag with SELECTED. In both ++ * cases, if a RIB block is present in FIB, it should be withdrawn. ++ */ + if (fib) + { + if (IS_ZEBRA_DEBUG_RIB) +@@ -1033,7 +1135,10 @@ + nexthop_active_update (rn, fib, 1); + } + +- /* Install new rib into forwarding table. */ ++ /* Regardless of some RIB entry being SELECTED or not before, now we can ++ * tell, that if a new winner exists, FIB is still not updated with this ++ * data, but ready to be. ++ */ + if (select) + { + if (IS_ZEBRA_DEBUG_RIB) +@@ -1350,16 +1455,127 @@ + SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); + + /* Link new rib to node.*/ ++ if (IS_ZEBRA_DEBUG_RIB) ++ zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib); + rib_addnode (rn, rib); + + /* Free implicit route.*/ + if (same) ++ { ++ if (IS_ZEBRA_DEBUG_RIB) ++ zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib); + rib_delnode (rn, same); ++ } + + route_unlock_node (rn); + return 0; + } + ++/* This function dumps the contents of a given RIB entry into ++ * standard debug log. Calling function name and IP prefix in ++ * question are passed as 1st and 2nd arguments. ++ */ ++ ++void rib_dump (const char * func, const struct prefix_ipv4 * p, const struct rib * rib) ++{ ++ char straddr1[INET_ADDRSTRLEN], straddr2[INET_ADDRSTRLEN]; ++ struct nexthop *nexthop; ++ ++ inet_ntop (AF_INET, &p->prefix, straddr1, INET_ADDRSTRLEN); ++ zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr1, p->prefixlen); ++ zlog_debug ++ ( ++ "%s: refcnt == %lu, uptime == %u, type == %u, table == %d", ++ func, ++ rib->refcnt, ++ rib->uptime, ++ rib->type, ++ rib->table ++ ); ++ zlog_debug ++ ( ++ "%s: metric == %u, distance == %u, flags == %u, status == %u", ++ func, ++ rib->metric, ++ rib->distance, ++ rib->flags, ++ rib->status ++ ); ++ zlog_debug ++ ( ++ "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u", ++ func, ++ rib->nexthop_num, ++ rib->nexthop_active_num, ++ rib->nexthop_fib_num ++ ); ++ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) ++ { ++ inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, straddr1, INET_ADDRSTRLEN); ++ inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, straddr2, INET_ADDRSTRLEN); ++ zlog_debug ++ ( ++ "%s: NH %s (%s) with flags %s%s%s", ++ func, ++ straddr1, ++ straddr2, ++ (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""), ++ (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""), ++ (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "") ++ ); ++ } ++ zlog_debug ("%s: dump complete", func); ++} ++ ++/* This is an exported helper to rtm_read() to dump the strange ++ * RIB entry found by rib_lookup_ipv4_route() ++ */ ++ ++void rib_lookup_and_dump (struct prefix_ipv4 * p) ++{ ++ struct route_table *table; ++ struct route_node *rn; ++ struct rib *rib; ++ char prefix_buf[INET_ADDRSTRLEN]; ++ ++ /* Lookup table. */ ++ table = vrf_table (AFI_IP, SAFI_UNICAST, 0); ++ if (! table) ++ { ++ zlog_err ("%s: vrf_table() returned NULL", __func__); ++ return; ++ } ++ ++ inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN); ++ /* Scan the RIB table for exactly matching RIB entry. */ ++ rn = route_node_lookup (table, (struct prefix *) p); ++ ++ /* No route for this prefix. */ ++ if (! rn) ++ { ++ zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen); ++ return; ++ } ++ ++ /* Unlock node. */ ++ route_unlock_node (rn); ++ ++ /* let's go */ ++ for (rib = rn->info; rib; rib = rib->next) ++ { ++ zlog_debug ++ ( ++ "%s: rn %p, rib %p: %s, %s", ++ __func__, ++ rn, ++ rib, ++ (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"), ++ (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected") ++ ); ++ rib_dump (__func__, p, rib); ++ } ++} ++ + int + rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib) + { +@@ -1408,10 +1624,24 @@ + + /* Link new rib to node.*/ + rib_addnode (rn, rib); ++ if (IS_ZEBRA_DEBUG_RIB) ++ { ++ zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry", ++ __func__, rn, rib); ++ rib_dump (__func__, p, rib); ++ } + + /* Free implicit route.*/ + if (same) ++ { ++ if (IS_ZEBRA_DEBUG_RIB) ++ { ++ zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry", ++ __func__, rn, same); ++ rib_dump (__func__, p, same); ++ } + rib_delnode (rn, same); ++ } + + route_unlock_node (rn); + return 0; diff --git a/net/quagga/files/patch-cvs-4-nexthop_active_update b/net/quagga/files/patch-cvs-4-nexthop_active_update new file mode 100644 index 000000000000..11ae35a428d5 --- /dev/null +++ b/net/quagga/files/patch-cvs-4-nexthop_active_update @@ -0,0 +1,47 @@ +--- zebra/zebra_rib.c.orig 2007-06-25 14:17:53.000000000 +0400 ++++ zebra/zebra_rib.c 2007-08-08 11:38:18.000000000 +0400 +@@ -795,27 +795,32 @@ + return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } + ++/* Iterate over all nexthops of the given RIB entry and refresh their ++ * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any ++ * nexthop is found to toggle the ACTIVE flag, the whole rib structure ++ * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is ++ * transparently passed to nexthop_active_check(). ++ * ++ * Return value is the new number of active nexthops. ++ */ ++ + static int + nexthop_active_update (struct route_node *rn, struct rib *rib, int set) + { + struct nexthop *nexthop; +- int active; ++ int prev_active, new_active; + + rib->nexthop_active_num = 0; + UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) +- { +- active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); +- +- nexthop_active_check (rn, rib, nexthop, set); +- if ((MULTIPATH_NUM == 0 || rib->nexthop_active_num < MULTIPATH_NUM) +- && active != CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) +- SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); +- +- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) +- rib->nexthop_active_num++; +- } ++ { ++ prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); ++ if ((new_active = nexthop_active_check (rn, rib, nexthop, set))) ++ rib->nexthop_active_num++; ++ if (prev_active != new_active) ++ SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); ++ } + return rib->nexthop_active_num; + } + diff --git a/net/quagga/files/patch-cvs-5-sendbuffer b/net/quagga/files/patch-cvs-5-sendbuffer new file mode 100644 index 000000000000..52187f7e0426 --- /dev/null +++ b/net/quagga/files/patch-cvs-5-sendbuffer @@ -0,0 +1,294 @@ +--- lib/sockopt.c.orig 2007-07-09 16:36:45.000000000 +0400 ++++ lib/sockopt.c 2007-08-02 17:38:50.000000000 +0400 +@@ -29,20 +29,49 @@ + int ret; + + if ( (ret = setsockopt (sock, SOL_SOCKET, SO_RCVBUF, (char *) + &size, sizeof (int))) < 0) + zlog_err ("fd %d: can't setsockopt SO_RCVBUF to %d: %s", + sock,size,safe_strerror(errno)); + + return ret; + } + ++int ++setsockopt_so_sendbuf (const int sock, int size) ++{ ++ int ret = setsockopt (sock, SOL_SOCKET, SO_SNDBUF, ++ (char *)&size, sizeof (int)); ++ ++ if (ret < 0) ++ zlog_err ("fd %d: can't setsockopt SO_SNDBUF to %d: %s", ++ sock, size, safe_strerror (errno)); ++ ++ return ret; ++} ++ ++int ++getsockopt_so_sendbuf (const int sock) ++{ ++ u_int32_t optval; ++ socklen_t optlen = sizeof (optval); ++ int ret = getsockopt (sock, SOL_SOCKET, SO_SNDBUF, ++ (char *)&optval, &optlen); ++ if (ret < 0) ++ { ++ zlog_err ("fd %d: can't getsockopt SO_SNDBUF: %d (%s)", ++ sock, errno, safe_strerror (errno)); ++ return ret; ++ } ++ return optval; ++} ++ + static void * + getsockopt_cmsg_data (struct msghdr *msgh, int level, int type) + { + struct cmsghdr *cmsg; + void *ptr = NULL; + + for (cmsg = ZCMSG_FIRSTHDR(msgh); + cmsg != NULL; + cmsg = CMSG_NXTHDR(msgh, cmsg)) + if (cmsg->cmsg_level == level && cmsg->cmsg_type) +--- lib/sockopt.h.orig 2007-07-09 16:36:45.000000000 +0400 ++++ lib/sockopt.h 2007-08-01 17:37:33.000000000 +0400 +@@ -16,20 +16,22 @@ + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + + #ifndef _ZEBRA_SOCKOPT_H + #define _ZEBRA_SOCKOPT_H + + extern int setsockopt_so_recvbuf (int sock, int size); ++extern int setsockopt_so_sendbuf (const int sock, int size); ++extern int getsockopt_so_sendbuf (const int sock); + + #ifdef HAVE_IPV6 + extern int setsockopt_ipv6_pktinfo (int, int); + extern int setsockopt_ipv6_checksum (int, int); + extern int setsockopt_ipv6_multicast_hops (int, int); + extern int setsockopt_ipv6_unicast_hops (int, int); + extern int setsockopt_ipv6_hoplimit (int, int); + extern int setsockopt_ipv6_multicast_loop (int, int); + #endif /* HAVE_IPV6 */ + +--- ospfd/ospfd.c.orig 2007-05-01 03:42:20.000000000 +0400 ++++ ospfd/ospfd.c 2007-08-01 19:07:46.000000000 +0400 +@@ -205,20 +205,22 @@ + new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker, + new, new->lsa_refresh_interval); + new->lsa_refresher_started = quagga_time (NULL); + + if ((new->fd = ospf_sock_init()) < 0) + { + zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open " + "a socket"); + exit(1); + } ++ new->maxsndbuflen = 0; ++ ospf_adjust_sndbuflen (new, OSPF_SNDBUFLEN_DEFAULT); + if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL) + { + zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf", + OSPF_MAX_PACKET_SIZE+1); + exit(1); + } + new->t_read = thread_add_read (master, ospf_read, new, new->fd); + new->oi_write_q = list_new (); + + return new; +--- ospfd/ospfd.h.orig 2006-10-18 00:45:04.000000000 +0400 ++++ ospfd/ospfd.h 2007-08-01 17:10:36.000000000 +0400 +@@ -122,20 +122,23 @@ + + /* OSPF Database Description flags. */ + #define OSPF_DD_FLAG_MS 0x01 + #define OSPF_DD_FLAG_M 0x02 + #define OSPF_DD_FLAG_I 0x04 + #define OSPF_DD_FLAG_ALL 0x07 + + #define OSPF_LS_REFRESH_SHIFT (60 * 15) + #define OSPF_LS_REFRESH_JITTER 60 + ++/* Initial send buffer size for ospfd raw sending socket. */ ++#define OSPF_SNDBUFLEN_DEFAULT 1024 ++ + /* OSPF master for system wide configuration and variables. */ + struct ospf_master + { + /* OSPF instance. */ + struct list *ospf; + + /* OSPF thread master. */ + struct thread_master *master; + + /* Zebra interface list. */ +@@ -259,20 +262,21 @@ + #ifdef HAVE_OPAQUE_LSA + struct thread *t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */ + #endif /* HAVE_OPAQUE_LSA */ + struct thread *t_maxage; /* MaxAge LSA remover timer. */ + struct thread *t_maxage_walker; /* MaxAge LSA checking timer. */ + struct thread *t_deferred_shutdown; /* deferred/stub-router shutdown timer*/ + + struct thread *t_write; + struct thread *t_read; + int fd; ++ int maxsndbuflen; + struct stream *ibuf; + struct list *oi_write_q; + + /* Distribute lists out of other route sources. */ + struct + { + char *name; + struct access_list *list; + } dlist[ZEBRA_ROUTE_MAX]; + #define DISTRIBUTE_NAME(O,T) (O)->dlist[T].name +--- ospfd/ospf_interface.c.orig 2007-04-22 17:26:38.000000000 +0400 ++++ ospfd/ospf_interface.c 2007-08-02 18:31:53.000000000 +0400 +@@ -774,20 +774,25 @@ + int + ospf_if_up (struct ospf_interface *oi) + { + if (oi == NULL) + return 0; + + if (oi->type == OSPF_IFTYPE_LOOPBACK) + OSPF_ISM_EVENT_SCHEDULE (oi, ISM_LoopInd); + else + { ++ struct ospf *ospf = ospf_lookup (); ++ if (ospf != NULL) ++ ospf_adjust_sndbuflen (ospf, oi->ifp->mtu); ++ else ++ zlog_warn ("%s: ospf_lookup() returned NULL"); + ospf_if_stream_set (oi); + OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceUp); + } + + return 1; + } + + int + ospf_if_down (struct ospf_interface *oi) + { +--- ospfd/ospf_network.c.orig 2005-05-09 22:37:56.000000000 +0400 ++++ ospfd/ospf_network.c 2007-08-01 20:03:26.000000000 +0400 +@@ -34,20 +34,21 @@ + extern struct zebra_privs_t ospfd_privs; + + #include "ospfd/ospfd.h" + #include "ospfd/ospf_network.h" + #include "ospfd/ospf_interface.h" + #include "ospfd/ospf_asbr.h" + #include "ospfd/ospf_lsa.h" + #include "ospfd/ospf_lsdb.h" + #include "ospfd/ospf_neighbor.h" + #include "ospfd/ospf_packet.h" ++#include "ospfd/ospf_dump.h" + + + + /* Join to the OSPF ALL SPF ROUTERS multicast group. */ + int + ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p, + unsigned int ifindex) + { + int ret; + +@@ -226,10 +227,44 @@ + zlog_warn ("Can't set pktinfo option for fd %d", ospf_sock); + + if (ospfd_privs.change (ZPRIVS_LOWER)) + { + zlog_err ("ospf_sock_init: could not lower privs, %s", + safe_strerror (errno) ); + } + + return ospf_sock; + } ++ ++void ++ospf_adjust_sndbuflen (struct ospf * ospf, int buflen) ++{ ++ int ret, newbuflen; ++ /* Check if any work has to be done at all. */ ++ if (ospf->maxsndbuflen >= buflen) ++ return; ++ if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) ++ zlog_debug ("%s: adjusting OSPF send buffer size to %d", ++ __func__, buflen); ++ if (ospfd_privs.change (ZPRIVS_RAISE)) ++ zlog_err ("%s: could not raise privs, %s", __func__, ++ safe_strerror (errno)); ++ /* Now we try to set SO_SNDBUF to what our caller has requested ++ * (OSPF_SNDBUFLEN_DEFAULT initially, which seems to be a sane ++ * default; or the MTU of a newly added interface). However, ++ * if the OS has truncated the actual buffer size to somewhat ++ * less or bigger size, try to detect it and update our records ++ * appropriately. ++ */ ++ ret = setsockopt_so_sendbuf (ospf->fd, buflen); ++ newbuflen = getsockopt_so_sendbuf (ospf->fd); ++ if (ret < 0 || newbuflen != buflen) ++ zlog_warn ("%s: tried to set SO_SNDBUF to %d, but got %d", ++ __func__, buflen, newbuflen); ++ if (newbuflen >= 0) ++ ospf->maxsndbuflen = newbuflen; ++ else ++ zlog_warn ("%s: failed to get SO_SNDBUF", __func__); ++ if (ospfd_privs.change (ZPRIVS_LOWER)) ++ zlog_err ("%s: could not lower privs, %s", __func__, ++ safe_strerror (errno)); ++} +--- ospfd/ospf_network.h.orig 2005-05-06 21:26:18.000000000 +0400 ++++ ospfd/ospf_network.h 2007-08-01 19:17:11.000000000 +0400 +@@ -27,12 +27,13 @@ + extern int ospf_if_add_allspfrouters (struct ospf *, struct prefix *, + unsigned int); + extern int ospf_if_drop_allspfrouters (struct ospf *, struct prefix *, + unsigned int); + extern int ospf_if_add_alldrouters (struct ospf *, struct prefix *, + unsigned int); + extern int ospf_if_drop_alldrouters (struct ospf *, struct prefix *, + unsigned int); + extern int ospf_if_ipmulticast (struct ospf *, struct prefix *, unsigned int); + extern int ospf_sock_init (void); ++extern void ospf_adjust_sndbuflen (struct ospf *, int); + + #endif /* _ZEBRA_OSPF_NETWORK_H */ +--- ospfd/ospf_packet.c.orig 2007-05-10 00:59:34.000000000 +0400 ++++ ospfd/ospf_packet.c 2007-08-01 18:32:36.000000000 +0400 +@@ -595,22 +595,26 @@ + assert (node); + oi = listgetdata (node); + assert (oi); + + #ifdef WANT_OSPF_WRITE_FRAGMENT + /* seed ipid static with low order bits of time */ + if (ipid == 0) + ipid = (time(NULL) & 0xffff); + #endif /* WANT_OSPF_WRITE_FRAGMENT */ + +- /* convenience - max OSPF data per packet */ +- maxdatasize = oi->ifp->mtu - sizeof (struct ip); ++ /* convenience - max OSPF data per packet, ++ * and reliability - not more data, than our ++ * socket can accept ++ */ ++ maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) - ++ sizeof (struct ip); + + /* Get one packet from queue. */ + op = ospf_fifo_head (oi->obuf); + assert (op); + assert (op->length >= OSPF_HEADER_SIZE); + + if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS) + || op->dst.s_addr == htonl (OSPF_ALLDROUTERS)) + ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex); + diff --git a/net/quagga/files/patch-cvs-6-RTF_DONE b/net/quagga/files/patch-cvs-6-RTF_DONE new file mode 100644 index 000000000000..0cdd1d5d3b56 --- /dev/null +++ b/net/quagga/files/patch-cvs-6-RTF_DONE @@ -0,0 +1,20 @@ +--- zebra/kernel_socket.c.orig 13 Aug 2007 16:03:07 -0000 1.45 ++++ zebra/kernel_socket.c 17 Aug 2007 12:38:10 -0000 +@@ -741,6 +741,8 @@ + /* Read destination and netmask and gateway from rtm message + structure. */ + flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen); ++ if (!(flags & RTF_DONE)) ++ return; + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: got rtm of type %d (%s)", __func__, rtm->rtm_type, + LOOKUP (rtm_type_str, rtm->rtm_type)); +@@ -794,8 +796,6 @@ + { + char buf[INET_ADDRSTRLEN], gate_buf[INET_ADDRSTRLEN]; + int ret; +- if (!(flags & RTF_DONE)) +- return; + if (! IS_ZEBRA_DEBUG_RIB) + return; + ret = rib_lookup_ipv4_route (&p, &gate); diff --git a/net/quagga/files/patch-cvs-7-ifm_read b/net/quagga/files/patch-cvs-7-ifm_read new file mode 100644 index 000000000000..41e04d69982b --- /dev/null +++ b/net/quagga/files/patch-cvs-7-ifm_read @@ -0,0 +1,18 @@ +--- zebra/kernel_socket.c.orig 17 Aug 2007 14:16:30 -0000 1.46 ++++ zebra/kernel_socket.c 21 Aug 2007 14:30:40 -0000 +@@ -472,6 +472,15 @@ + if_delete_update (ifp); + } + #endif /* RTM_IFANNOUNCE */ ++ if (if_is_up (ifp)) ++ { ++#if defined(__bsdi__) ++ if_kvm_get_mtu (ifp); ++#else ++ if_get_mtu (ifp); ++#endif /* __bsdi__ */ ++ if_get_metric (ifp); ++ } + } + + #ifdef HAVE_NET_RT_IFLIST |