File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / proto / ospf / lsack.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Aug 22 12:33:54 2017 UTC (6 years, 10 months ago) by misho
Branches: bird, MAIN
CVS tags: v1_6_8p3, v1_6_3p0, v1_6_3, HEAD
bird 1.6.3

    1: /*
    2:  *	BIRD -- OSPF
    3:  *
    4:  *	(c) 2000--2004 Ondrej Filip <feela@network.cz>
    5:  *	(c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
    6:  *	(c) 2009--2014 CZ.NIC z.s.p.o.
    7:  *
    8:  *	Can be freely distributed and used under the terms of the GNU GPL.
    9:  */
   10: 
   11: #include "ospf.h"
   12: 
   13: 
   14: /*
   15: struct ospf_lsack_packet
   16: {
   17:   struct ospf_packet hdr;
   18:   // union ospf_auth auth;
   19: 
   20:   struct ospf_lsa_header lsas[];
   21: };
   22: */
   23: 
   24: struct lsa_node
   25: {
   26:   node n;
   27:   struct ospf_lsa_header lsa;
   28: };
   29: 
   30: 
   31: static inline void
   32: ospf_lsack_body(struct ospf_proto *p, struct ospf_packet *pkt,
   33: 		struct ospf_lsa_header **body, uint *count)
   34: {
   35:   uint plen = ntohs(pkt->length);
   36:   uint hlen = ospf_pkt_hdrlen(p);
   37: 
   38:   *body = ((void *) pkt) + hlen;
   39:   *count = (plen - hlen) / sizeof(struct ospf_lsa_header);
   40: }
   41: 
   42: static void
   43: ospf_dump_lsack(struct ospf_proto *p, struct ospf_packet *pkt)
   44: {
   45:   struct ospf_lsa_header *lsas;
   46:   uint i, lsa_count;
   47: 
   48:   ASSERT(pkt->type == LSACK_P);
   49:   ospf_dump_common(p, pkt);
   50: 
   51:   ospf_lsack_body(p, pkt, &lsas, &lsa_count);
   52:   for (i = 0; i < lsa_count; i++)
   53:     ospf_dump_lsahdr(p, lsas + i);
   54: }
   55: 
   56: 
   57: void
   58: ospf_enqueue_lsack(struct ospf_neighbor *n, struct ospf_lsa_header *h_n, int queue)
   59: {
   60:   /* Note that h_n is in network endianity */
   61:   struct lsa_node *no = mb_alloc(n->pool, sizeof(struct lsa_node));
   62:   memcpy(&no->lsa, h_n, sizeof(struct ospf_lsa_header));
   63:   add_tail(&n->ackl[queue], NODE no);
   64:   DBG("Adding %s ack for %R, ID: %R, RT: %R, Type: %u\n",
   65:       (queue == ACKL_DIRECT) ? "direct" : "delayed",
   66:       n->rid, ntohl(h_n->id), ntohl(h_n->rt), h_n->type);
   67: }
   68: 
   69: void
   70: ospf_reset_lsack_queue(struct ospf_neighbor *n)
   71: {
   72:   struct lsa_node *no;
   73: 
   74:   WALK_LIST_FIRST(no, n->ackl[ACKL_DELAY])
   75:   {
   76:     rem_node(NODE no);
   77:     mb_free(no);
   78:   }
   79: }
   80: 
   81: static inline void
   82: ospf_send_lsack_(struct ospf_proto *p, struct ospf_neighbor *n, int queue)
   83: {
   84:   struct ospf_iface *ifa = n->ifa;
   85:   struct ospf_lsa_header *lsas;
   86:   struct ospf_packet *pkt;
   87:   struct lsa_node *no;
   88:   uint i, lsa_max, length;
   89: 
   90:   /* RFC 2328 13.5 */
   91: 
   92:   pkt = ospf_tx_buffer(ifa);
   93:   ospf_pkt_fill_hdr(ifa, pkt, LSACK_P);
   94:   ospf_lsack_body(p, pkt, &lsas, &lsa_max);
   95: 
   96:   for (i = 0; i < lsa_max && !EMPTY_LIST(n->ackl[queue]); i++)
   97:   {
   98:     no = (struct lsa_node *) HEAD(n->ackl[queue]);
   99:     memcpy(&lsas[i], &no->lsa, sizeof(struct ospf_lsa_header));
  100:     DBG("Iter %u ID: %R, RT: %R, Type: %04x\n",
  101: 	i, ntohl(lsas[i].id), ntohl(lsas[i].rt), lsas[i].type);
  102:     rem_node(NODE no);
  103:     mb_free(no);
  104:   }
  105: 
  106:   length = ospf_pkt_hdrlen(p) + i * sizeof(struct ospf_lsa_header);
  107:   pkt->length = htons(length);
  108: 
  109:   OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet sent via %s", ifa->ifname);
  110: 
  111:   if (ifa->type == OSPF_IT_BCAST)
  112:   {
  113:     if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
  114:       ospf_send_to_all(ifa);
  115:     else
  116:       ospf_send_to_des(ifa);
  117:   }
  118:   else
  119:     ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
  120: }
  121: 
  122: void
  123: ospf_send_lsack(struct ospf_proto *p, struct ospf_neighbor *n, int queue)
  124: {
  125:   while (!EMPTY_LIST(n->ackl[queue]))
  126:     ospf_send_lsack_(p, n, queue);
  127: }
  128: 
  129: void
  130: ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
  131: 		   struct ospf_neighbor *n)
  132: {
  133:   struct ospf_proto *p = ifa->oa->po;
  134:   struct ospf_lsa_header lsa, *lsas;
  135:   struct top_hash_entry *ret, *en;
  136:   uint i, lsa_count;
  137:   u32 lsa_type, lsa_domain;
  138: 
  139:   /* RFC 2328 13.7 */
  140: 
  141:   /* No need to check length, lsack has only basic header */
  142: 
  143:   OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet received from nbr %R on %s", n->rid, ifa->ifname);
  144: 
  145:   if (n->state < NEIGHBOR_EXCHANGE)
  146:   {
  147:     OSPF_TRACE(D_PACKETS, "LSACK packet ignored - lesser state than Exchange");
  148:     return;
  149:   }
  150: 
  151:   ospf_neigh_sm(n, INM_HELLOREC);	/* Not in RFC */
  152: 
  153:   ospf_lsack_body(p, pkt, &lsas, &lsa_count);
  154:   for (i = 0; i < lsa_count; i++)
  155:   {
  156:     lsa_ntoh_hdr(&lsas[i], &lsa);
  157:     lsa_get_type_domain(&lsa, n->ifa, &lsa_type, &lsa_domain);
  158: 
  159:     ret = ospf_hash_find(n->lsrth, lsa_domain, lsa.id, lsa.rt, lsa_type);
  160:     if (!ret)
  161:       continue;
  162: 
  163:     if (lsa_comp(&lsa, &ret->lsa) != CMP_SAME)
  164:     {
  165:       OSPF_TRACE(D_PACKETS, "Strange LSACK from nbr %R on %s", n->rid, ifa->ifname);
  166:       OSPF_TRACE(D_PACKETS, "    Type: %04x, Id: %R, Rt: %R",
  167: 		 lsa_type, lsa.id, lsa.rt);
  168:       OSPF_TRACE(D_PACKETS, "    I have: Seq: %08x, Age: %4u, Sum: %04x",
  169: 		 ret->lsa.sn, ret->lsa.age, ret->lsa.checksum);
  170:       OSPF_TRACE(D_PACKETS, "    It has: Seq: %08x, Age: %4u, Sum: %04x",
  171: 		 lsa.sn, lsa.age, lsa.checksum);
  172:       continue;
  173:     }
  174: 
  175:     DBG("Deleting LSA (Type: %04x Id: %R Rt: %R) from lsrtl for neighbor %R\n",
  176: 	lsa_type, lsa.id, lsa.rt, n->rid);
  177: 
  178:     en = ospf_hash_find_entry(p->gr, ret);
  179:     ospf_lsa_lsrt_down_(en, n, ret);
  180:   }
  181: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>