[quagga-dev 8370] Re: Expose announced routes through SNMP

Stephane Bagneris sbagneri at yahoo-inc.com
Tue Nov 23 23:56:57 GMT 2010


In the interest of speed and since the modification is rather minor I will
provide it directly here in a diff. I do not have access to a public git
repository just yet but I will do my best to provide the mod this way soon.

As for testing, this is a new feature that has only been deployed to a
handful of sandboxes for now. It seems to work pretty well however. I
believe this to be a useful feature that could benefit the community.

As for extending the bgp MIB which is what I am doing now, I do not think
this is a viable solution long term. The easiest simplest way to get proper
OID's would be to extend the zebra MIB. I must admit going through the IETF
to extend the current bgp MIB used by just about everybody doing routing out
there seems rather hard to achieve.

Here is the final patch for bgpd/bgp_snmp.c to provide the added
functionality:

*** quagga-0.99.17/bgpd/bgp_snmp.c      2010-08-19 02:32:24.000000000 -0700
--- quagga-0.99.17_mod/bgpd/bgp_snmp.c  2010-11-23 15:23:24.000000000 -0800
***************
*** 111,116 ****
--- 111,121 ----
  #define BGP4PATHATTRBEST                     13
  #define BGP4PATHATTRUNKNOWN                  14

+ /* Custom MIB bgp4SentPathAttrTable */
+ #define BGP4SENTPATHATTRIPADDRPREFIX          1
+ #define BGP4SENTPATHATTRIPADDRPREFIXLEN       2
+ #define BGP4SENTPATHATTRSTATUS                3
+ 
  /* SNMP value hack. */
  #define INTEGER ASN_INTEGER
  #define INTEGER32 ASN_INTEGER
***************
*** 141,146 ****
--- 146,153 ----
                              int, size_t *, WriteMethod **);
  static u_char *bgp4PathAttrTable (struct variable *, oid [], size_t *,
                                  int, size_t *, WriteMethod **);
+ static u_char *bgp4SentPathAttrTable (struct variable *, oid [], size_t *,
+                                 int, size_t *, WriteMethod **);
  /* static u_char *bgpTraps (); */

  struct variable bgp_variables[] =
***************
*** 245,250 ****
--- 252,264 ----
     3, {6, 1, 13}},
    {BGP4PATHATTRUNKNOWN,       OCTET_STRING, RONLY, bgp4PathAttrTable,
     3, {6, 1, 14}},
+   /* BGP-4 sent path attribute table. */
+   {BGP4SENTPATHATTRIPADDRPREFIX, IPADDRESS, RONLY, bgp4SentPathAttrTable,
+    3, {7, 1, 1}},
+   {BGP4SENTPATHATTRIPADDRPREFIXLEN, INTEGER, RONLY, bgp4SentPathAttrTable,
+    3, {7, 1, 2}},
+   {BGP4SENTPATHATTRSTATUS,    INTEGER, RONLY, bgp4SentPathAttrTable,
+    3, {7, 1, 3}},
  };



***************
*** 835,840 ****
--- 849,1001 ----
      }
    return NULL;
  }
+ 
+ static struct bgp_info *
+ bgp4SentPathAttrLookup (struct variable *v, oid name[], size_t *length,
+               struct bgp *bgp, struct prefix_ipv4 *addr, int exact)
+ {
+       oid *offset;
+       int offsetlen;
+       struct bgp_info *binfo;
+       struct bgp_info *min;
+       struct bgp_node *rn;
+       unsigned int len;
+ 
+ #define BGP_SENT_PATHATTR_ENTRY_OFFSET \
+                 (IN_ADDR_SIZE)
+ 
+       if (exact) {
+               if (*length - v->namelen != BGP_SENT_PATHATTR_ENTRY_OFFSET)
+                       return NULL;
+ 
+           /* Set OID offset for prefix. */
+               offset = name + v->namelen;
+           oid2in_addr (offset, IN_ADDR_SIZE, &addr->prefix);
+           offset += IN_ADDR_SIZE;
+ 
+               for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_UNICAST]);
rn; rn = bgp_route_next (rn)) {
+                       if (rn->info != NULL) {
+                               for (binfo = rn->info; binfo; binfo =
binfo->next) {
+                                       u_int32_t destination;
+                                       destination = ntohl
(rn->p.u.prefix4.s_addr);
+                                       if (IN_CLASSC (destination) &&
rn->p.prefixlen == 24)
+                                               continue;
+                                       if (IN_CLASSB (destination) &&
rn->p.prefixlen == 16)
+                                               continue;
+                                       if (IN_CLASSA (destination) &&
rn->p.prefixlen == 8)
+                                               continue;
+                                       if (ntohl (addr->prefix.s_addr) !=
ntohl (rn->p.u.prefix4.s_addr))
+                                               continue;
+                                       addr->family = rn->p.family;
+                                       addr->prefixlen = rn->p.prefixlen;
+                                       bgp_unlock_node (rn);
+                                       return binfo;
+                               }
+                       }
+               }
+               return NULL;
+       }
+       else {
+               offset = name + v->namelen;
+               offsetlen = *length - v->namelen;
+           len = offsetlen;
+ 
+           if (offsetlen == 0)
+               rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_UNICAST]);
+           else {
+               if (len > IN_ADDR_SIZE)
+                       len = IN_ADDR_SIZE;
+ 
+               oid2in_addr (offset, len, &addr->prefix);
+               offset += IN_ADDR_SIZE;
+               offsetlen -= IN_ADDR_SIZE;
+               addr->prefixlen = len * 8;
+               rn = bgp_node_get (bgp->rib[AFI_IP][SAFI_UNICAST],
+                                      (struct prefix *) addr);
+           }
+           if (! rn)
+               return NULL;
+           do {
+               min = NULL;
+               for (binfo = rn->info; binfo; binfo = binfo->next) {
+                       u_int32_t destination;
+                       destination = ntohl (rn->p.u.prefix4.s_addr);
+                       if (IN_CLASSC (destination) && rn->p.prefixlen ==
24)
+                               continue;
+                       if (IN_CLASSB (destination) && rn->p.prefixlen ==
16)
+                               continue;
+                       if (IN_CLASSA (destination) && rn->p.prefixlen == 8)
+                               continue;
+                       if (ntohl (addr->prefix.s_addr) < ntohl
(rn->p.u.prefix4.s_addr))
+                               min = binfo;
+               }
+               if (min) {
+                       *length = v->namelen +
BGP_SENT_PATHATTR_ENTRY_OFFSET;
+                       offset = name + v->namelen;
+                       oid_copy_addr (offset, &rn->p.u.prefix4,
IN_ADDR_SIZE);
+                       offset += IN_ADDR_SIZE;
+                       addr->prefix = rn->p.u.prefix4;
+                       addr->prefixlen = rn->p.prefixlen;
+                       bgp_unlock_node (rn);
+                       return min;
+               }
+           }
+           while ((rn = bgp_route_next (rn)) != NULL);
+       }
+       return NULL;
+ }
+ 
+ static u_char *
+ bgp4SentPathAttrTable (struct variable *v, oid name[], size_t *length,
+                  int exact, size_t *var_len, WriteMethod **write_method)
+ {
+       struct bgp *bgp;
+       struct bgp_info *binfo;
+       struct prefix_ipv4 addr;
+ 
+       bgp = bgp_get_default ();
+         if (! bgp)
+           return NULL;
+ 
+   memset (&addr, 0, sizeof (struct prefix_ipv4));
+ 
+   binfo = bgp4SentPathAttrLookup (v, name, length, bgp, &addr, exact);
+   if (! binfo)
+     return NULL;
+ 
+   switch (v->magic)
+     {
+     case BGP4SENTPATHATTRIPADDRPREFIX: /* 1 */
+       return SNMP_IPADDRESS (addr.prefix);
+       break;
+     case BGP4SENTPATHATTRIPADDRPREFIXLEN: /* 2 */
+       return SNMP_INTEGER (addr.prefixlen);
+       break;
+     case BGP4SENTPATHATTRSTATUS:      /* 3 */
+ #define BGP4_SentPathAttrStatus_false 1
+ #define BGP4_SentPathAttrStatus_true  2
+         if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
+                 return SNMP_INTEGER (BGP4_SentPathAttrStatus_false);
+         else if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
+                 return SNMP_INTEGER (BGP4_SentPathAttrStatus_false);
+         else if (binfo->extra && binfo->extra->suppress)
+                 return SNMP_INTEGER (BGP4_SentPathAttrStatus_false);
+         else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) {
+                 if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+                         return SNMP_INTEGER
(BGP4_SentPathAttrStatus_false);
+                 else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
+                         return SNMP_INTEGER
(BGP4_SentPathAttrStatus_false);
+                 else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
+                         return SNMP_INTEGER
(BGP4_SentPathAttrStatus_true);
+                 else
+                         return SNMP_INTEGER
(BGP4_SentPathAttrStatus_false);
+         }
+         else
+                 return SNMP_INTEGER (BGP4_SentPathAttrStatus_false);
+       break;
+     }
+   return NULL;
+ }


  /* BGP Traps. */
  struct trap_object bgpTrapList[] =


Regards,
Stephane.


On 11/23/10 12:45 PM, "Greg Troxel" <gdt at ir.bbn.com> wrote:

> 
> You can certainly post the patch, but the preferred method is to have a
> public git repository that's a clone of the official one with a feature
> branch with your work (based on tip of master or the latest release
> tag).  See HACKING in the current repository.  Then send a note
> describing how much testing the change has had - sounds like it's been
> run quite a bit in operations - on what OS/CPU/etc. combinations.
> 
> I'm not sure what you mean about custom OID, but assuming you have
> extended the MIB beyond the standards, you should perhaps address that
> within the IETF.  At least submit an ID describing what's needed.  I
> would be reluctant to add code with private codepoints to quagga, but
> it's not a line in the sand.  Regardless it is helpful to the community
> to post the patch.




More information about the Quagga-dev mailing list