Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (4.89 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 2000-2004 Ondrej Filip <feela@network.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9
#include "ospf.h"
10

    
11

    
12
struct ospf_lsack_packet
13
{
14
  struct ospf_packet ospf_packet;
15
  struct ospf_lsa_header lsh[];
16
};
17

    
18

    
19
char *s_queue[] = { "direct", "delayed" };
20

    
21

    
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
  unsigned int i, j;
30
  j = (ntohs(op->length) - sizeof(struct ospf_lsack_packet)) /
31
    sizeof(struct ospf_lsa_header);
32

    
33
  for (i = 0; i < j; i++)
34
    ospf_dump_lsahdr(p, pkt->lsh + i);
35
}
36

    
37

    
38
/*
39
 * =====================================
40
 * Note, that h is in network endianity!
41
 * =====================================
42
 */
43

    
44
void
45
ospf_lsack_enqueue(struct ospf_neighbor *n, struct ospf_lsa_header *h,
46
                   int queue)
47
{
48
  struct lsah_n *no = mb_alloc(n->pool, sizeof(struct lsah_n));
49
  memcpy(&no->lsa, h, sizeof(struct ospf_lsa_header));
50
  add_tail(&n->ackl[queue], NODE no);
51
  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
}
54

    
55
void
56
ospf_lsack_send(struct ospf_neighbor *n, int queue)
57
{
58
  struct ospf_packet *op;
59
  struct ospf_lsack_packet *pk;
60
  u16 len, i = 0;
61
  struct ospf_lsa_header *h;
62
  struct lsah_n *no;
63
  struct ospf_iface *ifa = n->ifa;
64
  struct proto *p = &n->ifa->oa->po->proto;
65

    
66
  if (EMPTY_LIST(n->ackl[queue]))
67
    return;
68

    
69
  pk = ospf_tx_buffer(ifa);
70
  op = &pk->ospf_packet;
71

    
72
  ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
73
  h = pk->lsh;
74

    
75
  while (!EMPTY_LIST(n->ackl[queue]))
76
  {
77
    no = (struct lsah_n *) HEAD(n->ackl[queue]);
78
    memcpy(h + i, &no->lsa, sizeof(struct ospf_lsa_header));
79
    DBG("Iter %u ID: %R, RT: %R, Type: %04x\n", i, ntohl((h + i)->id),
80
        ntohl((h + i)->rt), (h + i)->type);
81
    i++;
82
    rem_node(NODE no);
83
    mb_free(no);
84
    if ((i * sizeof(struct ospf_lsa_header) +
85
         sizeof(struct ospf_lsack_packet)) > ospf_pkt_maxsize(n->ifa))
86
    {
87
      if (!EMPTY_LIST(n->ackl[queue]))
88
      {
89
        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

    
95
        OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->ifname);
96

    
97
        if (ifa->type == OSPF_IT_BCAST)
98
        {
99
          if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
100
            ospf_send_to_all(ifa);
101
          else if (ifa->cf->real_bcast)
102
            ospf_send_to_bdr(ifa);
103
          else
104
            ospf_send_to(ifa, AllDRouters);
105
        }
106
        else
107
        {
108
          if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
109
            ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
110
          else
111
            ospf_send_to_bdr(ifa);
112
        }
113

    
114
        ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
115
        i = 0;
116
      }
117
    }
118
  }
119

    
120
  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

    
124
  OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->ifname);
125

    
126
  if (ifa->type == OSPF_IT_BCAST)
127
  {
128
    if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
129
      ospf_send_to_all(ifa);
130
    else if (ifa->cf->real_bcast)
131
      ospf_send_to_bdr(ifa);
132
    else
133
      ospf_send_to(ifa, AllDRouters);
134
  }
135
  else
136
    ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
137
}
138

    
139
void
140
ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
141
                   struct ospf_neighbor *n)
142
{
143
  struct proto *p = &ifa->oa->po->proto;
144
  struct ospf_lsa_header lsa;
145
  struct top_hash_entry *en;
146
  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

    
155
  struct ospf_lsack_packet *ps = (void *) ps_i;
156
  OSPF_PACKET(ospf_dump_lsack, ps, "LSACK packet received from %I via %s", n->ip, ifa->ifname);
157

    
158
  ospf_neigh_sm(n, INM_HELLOREC);
159

    
160
  if (n->state < NEIGHBOR_EXCHANGE)
161
    return;
162

    
163
  lsano = (size - sizeof(struct ospf_lsack_packet)) /
164
    sizeof(struct ospf_lsa_header);
165
  for (i = 0; i < lsano; i++)
166
  {
167
    ntohlsah(ps->lsh + i, &lsa);
168
    u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
169
    if ((en = ospf_hash_find_header(n->lsrth, dom, &lsa)) == NULL)
170
      continue;                        /* pg 155 */
171

    
172
    if (lsa_comp(&lsa, &en->lsa) != CMP_SAME)        /* pg 156 */
173
    {
174
      if ((lsa.sn == LSA_MAXSEQNO) && (lsa.age == LSA_MAXAGE))
175
        continue;
176

    
177
      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
                 en->lsa.age, en->lsa.sn, en->lsa.checksum);
182
      OSPF_TRACE(D_PACKETS, "He has: Age: %4u, Seq: %08x, Sum: %04x",
183
                 lsa.age, lsa.sn, lsa.checksum);
184
      continue;
185
    }
186

    
187
    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
    s_rem_node(SNODE en);
190
    ospf_hash_delete(n->lsrth, en);
191
  }
192
}