Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / lsack.c @ 48e5f32d

History | View | Annotate | Download (4.89 KB)

1 de769e24 Ondrej Filip
/*
2
 *        BIRD -- OSPF
3
 *
4 c76ba51a Ondrej Filip
 *        (c) 2000-2004 Ondrej Filip <feela@network.cz>
5 de769e24 Ondrej Filip
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8
9
#include "ospf.h"
10
11 c3226991 Ondrej Zajicek
12
struct ospf_lsack_packet
13
{
14
  struct ospf_packet ospf_packet;
15
  struct ospf_lsa_header lsh[];
16
};
17
18
19 fb9bf688 Ondrej Filip
char *s_queue[] = { "direct", "delayed" };
20 67315ef6 Ondrej Filip
21 8298d780 Ondrej Zajicek
22
static void ospf_dump_lsack(struct proto *p, struct ospf_lsack_packet *pkt)
23
{
24
  struct ospf_packet *op = &pkt->ospf_packet;
25
26
  ASSERT(op->type == LSACK_P);
27
  ospf_dump_common(p, op);
28
29 a6bc04d5 Ondrej Zajicek
  unsigned int i, j;
30 8298d780 Ondrej Zajicek
  j = (ntohs(op->length) - sizeof(struct ospf_lsack_packet)) /
31
    sizeof(struct ospf_lsa_header);
32
33
  for (i = 0; i < j; i++)
34 c3226991 Ondrej Zajicek
    ospf_dump_lsahdr(p, pkt->lsh + i);
35 8298d780 Ondrej Zajicek
}
36
37
38 c76ba51a Ondrej Filip
/*
39
 * =====================================
40
 * Note, that h is in network endianity!
41
 * =====================================
42
 */
43 fb9bf688 Ondrej Filip
44 67315ef6 Ondrej Filip
void
45 fb9bf688 Ondrej Filip
ospf_lsack_enqueue(struct ospf_neighbor *n, struct ospf_lsa_header *h,
46 8e15e048 Ondrej Filip
                   int queue)
47 67315ef6 Ondrej Filip
{
48 8e15e048 Ondrej Filip
  struct lsah_n *no = mb_alloc(n->pool, sizeof(struct lsah_n));
49 fb9bf688 Ondrej Filip
  memcpy(&no->lsa, h, sizeof(struct ospf_lsa_header));
50 c76ba51a Ondrej Filip
  add_tail(&n->ackl[queue], NODE no);
51 3aab39f5 Ondrej Zajicek
  DBG("Adding (%s) ack for %R, ID: %R, RT: %R, Type: %u\n", s_queue[queue],
52
      n->rid, ntohl(h->id), ntohl(h->rt), h->type);
53 67315ef6 Ondrej Filip
}
54
55
void
56 c76ba51a Ondrej Filip
ospf_lsack_send(struct ospf_neighbor *n, int queue)
57 67315ef6 Ondrej Filip
{
58
  struct ospf_packet *op;
59
  struct ospf_lsack_packet *pk;
60 fb9bf688 Ondrej Filip
  u16 len, i = 0;
61 67315ef6 Ondrej Filip
  struct ospf_lsa_header *h;
62
  struct lsah_n *no;
63 fb9bf688 Ondrej Filip
  struct ospf_iface *ifa = n->ifa;
64 86c84d76 Ondrej Filip
  struct proto *p = &n->ifa->oa->po->proto;
65 67315ef6 Ondrej Filip
66 fb9bf688 Ondrej Filip
  if (EMPTY_LIST(n->ackl[queue]))
67
    return;
68 c76ba51a Ondrej Filip
69 e7b76b97 Ondrej Zajicek
  pk = ospf_tx_buffer(ifa);
70 353729f5 Ondrej Zajicek
  op = &pk->ospf_packet;
71 67315ef6 Ondrej Filip
72 3e2bd0f1 Ondrej Filip
  ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
73 c3226991 Ondrej Zajicek
  h = pk->lsh;
74 67315ef6 Ondrej Filip
75 fb9bf688 Ondrej Filip
  while (!EMPTY_LIST(n->ackl[queue]))
76 67315ef6 Ondrej Filip
  {
77 fb9bf688 Ondrej Filip
    no = (struct lsah_n *) HEAD(n->ackl[queue]);
78
    memcpy(h + i, &no->lsa, sizeof(struct ospf_lsa_header));
79 69fbf9a2 Ondrej Zajicek
    DBG("Iter %u ID: %R, RT: %R, Type: %04x\n", i, ntohl((h + i)->id),
80 3aab39f5 Ondrej Zajicek
        ntohl((h + i)->rt), (h + i)->type);
81 69fbf9a2 Ondrej Zajicek
    i++;
82 023f5e86 Ondrej Filip
    rem_node(NODE no);
83 284c43ff Ondrej Filip
    mb_free(no);
84 fb9bf688 Ondrej Filip
    if ((i * sizeof(struct ospf_lsa_header) +
85 3e2bd0f1 Ondrej Filip
         sizeof(struct ospf_lsack_packet)) > ospf_pkt_maxsize(n->ifa))
86 67315ef6 Ondrej Filip
    {
87 fb9bf688 Ondrej Filip
      if (!EMPTY_LIST(n->ackl[queue]))
88 67315ef6 Ondrej Filip
      {
89 fb9bf688 Ondrej Filip
        len =
90
          sizeof(struct ospf_lsack_packet) +
91
          i * sizeof(struct ospf_lsa_header);
92
        op->length = htons(len);
93
        DBG("Sending and continuing! Len=%u\n", len);
94 8298d780 Ondrej Zajicek
95 48e5f32d Ondrej Zajicek
        OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->ifname);
96 8298d780 Ondrej Zajicek
97 fb9bf688 Ondrej Filip
        if (ifa->type == OSPF_IT_BCAST)
98 67315ef6 Ondrej Filip
        {
99 fb9bf688 Ondrej Filip
          if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
100 95127cbb Ondrej Zajicek
            ospf_send_to_all(ifa);
101
          else if (ifa->cf->real_bcast)
102
            ospf_send_to_bdr(ifa);
103 67315ef6 Ondrej Filip
          else
104 f9c799a0 Ondrej Zajicek
            ospf_send_to(ifa, AllDRouters);
105 67315ef6 Ondrej Filip
        }
106
        else
107
        {
108 fb9bf688 Ondrej Filip
          if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
109 f9c799a0 Ondrej Zajicek
            ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
110 eb436e16 Ondrej Filip
          else
111 f9c799a0 Ondrej Zajicek
            ospf_send_to_bdr(ifa);
112 67315ef6 Ondrej Filip
        }
113 284c43ff Ondrej Filip
114 3e2bd0f1 Ondrej Filip
        ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
115 fb9bf688 Ondrej Filip
        i = 0;
116 67315ef6 Ondrej Filip
      }
117
    }
118
  }
119
120 fb9bf688 Ondrej Filip
  len = sizeof(struct ospf_lsack_packet) + i * sizeof(struct ospf_lsa_header);
121
  op->length = htons(len);
122
  DBG("Sending! Len=%u\n", len);
123 8298d780 Ondrej Zajicek
124 48e5f32d Ondrej Zajicek
  OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->ifname);
125 8298d780 Ondrej Zajicek
126 fb9bf688 Ondrej Filip
  if (ifa->type == OSPF_IT_BCAST)
127 67315ef6 Ondrej Filip
  {
128 fb9bf688 Ondrej Filip
    if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
129 95127cbb Ondrej Zajicek
      ospf_send_to_all(ifa);
130
    else if (ifa->cf->real_bcast)
131
      ospf_send_to_bdr(ifa);
132 67315ef6 Ondrej Filip
    else
133 f9c799a0 Ondrej Zajicek
      ospf_send_to(ifa, AllDRouters);
134 67315ef6 Ondrej Filip
  }
135
  else
136 f9c799a0 Ondrej Zajicek
    ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
137 de769e24 Ondrej Filip
}
138
139
void
140 c3226991 Ondrej Zajicek
ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
141
                   struct ospf_neighbor *n)
142 de769e24 Ondrej Filip
{
143 a6bc04d5 Ondrej Zajicek
  struct proto *p = &ifa->oa->po->proto;
144 c3226991 Ondrej Zajicek
  struct ospf_lsa_header lsa;
145 4bf41ac8 Ondrej Filip
  struct top_hash_entry *en;
146 a6bc04d5 Ondrej Zajicek
  unsigned int i, lsano;
147
148
  unsigned int size = ntohs(ps_i->length);
149
  if (size < sizeof(struct ospf_lsack_packet))
150
  {
151
    log(L_ERR "Bad OSPF LSACK packet from %I -  too short (%u B)", n->ip, size);
152
    return;
153
  }
154 ebff007f Ondrej Filip
155 a6bc04d5 Ondrej Zajicek
  struct ospf_lsack_packet *ps = (void *) ps_i;
156 48e5f32d Ondrej Zajicek
  OSPF_PACKET(ospf_dump_lsack, ps, "LSACK packet received from %I via %s", n->ip, ifa->ifname);
157 8298d780 Ondrej Zajicek
158 4bb9ce56 Ondrej Filip
  ospf_neigh_sm(n, INM_HELLOREC);
159 9669362f Ondrej Filip
160 fb9bf688 Ondrej Filip
  if (n->state < NEIGHBOR_EXCHANGE)
161
    return;
162 9669362f Ondrej Filip
163 a6bc04d5 Ondrej Zajicek
  lsano = (size - sizeof(struct ospf_lsack_packet)) /
164 4bf41ac8 Ondrej Filip
    sizeof(struct ospf_lsa_header);
165 a6bc04d5 Ondrej Zajicek
  for (i = 0; i < lsano; i++)
166 4bf41ac8 Ondrej Filip
  {
167 c3226991 Ondrej Zajicek
    ntohlsah(ps->lsh + i, &lsa);
168 b49e6f5a Ondrej Zajicek
    u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
169
    if ((en = ospf_hash_find_header(n->lsrth, dom, &lsa)) == NULL)
170 2e10a170 Ondrej Filip
      continue;                        /* pg 155 */
171 4bf41ac8 Ondrej Filip
172 9b7de4c4 Ondrej Filip
    if (lsa_comp(&lsa, &en->lsa) != CMP_SAME)        /* pg 156 */
173 4bf41ac8 Ondrej Filip
    {
174 fb9bf688 Ondrej Filip
      if ((lsa.sn == LSA_MAXSEQNO) && (lsa.age == LSA_MAXAGE))
175
        continue;
176 37282678 Ondrej Filip
177 34a877cc Ondrej Zajicek
      OSPF_TRACE(D_PACKETS, "Strange LSACK from %I", n->ip);
178
      OSPF_TRACE(D_PACKETS, "Type: %04x, Id: %R, Rt: %R",
179
                 lsa.type, lsa.id, lsa.rt);
180
      OSPF_TRACE(D_PACKETS, "I have: Age: %4u, Seq: %08x, Sum: %04x",
181 fb9bf688 Ondrej Filip
                 en->lsa.age, en->lsa.sn, en->lsa.checksum);
182 34a877cc Ondrej Zajicek
      OSPF_TRACE(D_PACKETS, "He has: Age: %4u, Seq: %08x, Sum: %04x",
183 fb9bf688 Ondrej Filip
                 lsa.age, lsa.sn, lsa.checksum);
184 4bf41ac8 Ondrej Filip
      continue;
185
    }
186
187 3aab39f5 Ondrej Zajicek
    DBG("Deleting LS Id: %R RT: %R Type: %u from LS Retl for neighbor %R\n",
188
        lsa.id, lsa.rt, lsa.type, n->rid);
189 4bf41ac8 Ondrej Filip
    s_rem_node(SNODE en);
190 fb9bf688 Ondrej Filip
    ospf_hash_delete(n->lsrth, en);
191
  }
192 de769e24 Ondrej Filip
}