Revision cf7f0645

View differences:

nest/iface.c
152 152
}
153 153

  
154 154
static void
155
ifa_notify_change(unsigned c, struct ifa *a)
155
ifa_notify_change_dep(unsigned c, struct ifa *a)
156 156
{
157 157
  struct proto *p;
158 158

  
159 159
  DBG("IFA change notification (%x) for %s:%I\n", c, a->iface->name, a->ip);
160

  
160 161
  WALK_LIST(p, active_proto_list)
161 162
    ifa_send_notify(p, c, a);
162 163
}
163 164

  
164 165
static inline void
166
ifa_notify_change(unsigned c, struct ifa *a)
167
{
168
  neigh_ifa_update(a);
169
  ifa_notify_change_dep(c, a);
170
}
171

  
172
static inline void
165 173
if_send_notify(struct proto *p, unsigned c, struct iface *i)
166 174
{
167 175
  if (p->if_notify)
......
197 205

  
198 206
  if (c & IF_CHANGE_UP)
199 207
    neigh_if_up(i);
208

  
200 209
  if (c & IF_CHANGE_DOWN)
201 210
    WALK_LIST(a, i->addrs)
202 211
      {
203 212
	a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
204
	ifa_notify_change(IF_CHANGE_DOWN, a);
213
	ifa_notify_change_dep(IF_CHANGE_DOWN, a);
205 214
      }
206 215

  
207 216
  WALK_LIST(p, active_proto_list)
......
211 220
    WALK_LIST(a, i->addrs)
212 221
      {
213 222
	a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
214
	ifa_notify_change(IF_CHANGE_UP, a);
223
	ifa_notify_change_dep(IF_CHANGE_UP, a);
215 224
      }
216 225

  
217 226
  if ((c & (IF_CHANGE_UP | IF_CHANGE_DOWN | IF_CHANGE_LINK)) == IF_CHANGE_LINK)
nest/iface.h
131 131
void neigh_if_up(struct iface *);
132 132
void neigh_if_down(struct iface *);
133 133
void neigh_if_link(struct iface *);
134
void neigh_ifa_update(struct ifa *);
134 135
void neigh_init(struct pool *);
135 136

  
136 137
/*
nest/neighbor.c
103 103
 * If the node is not connected directly or *@a is not a valid unicast
104 104
 * IP address, neigh_find() returns %NULL.
105 105
 */
106

  
107

  
108 106
neighbor *
109 107
neigh_find(struct proto *p, ip_addr *a, unsigned flags)
110 108
{
......
219 217
  debug("\n");
220 218
}
221 219

  
220
static void
221
neigh_up(neighbor *n, struct iface *i, int scope)
222
{
223
  n->iface = i;
224
  n->scope = scope;
225
  add_tail(&i->neighbors, &n->if_n);
226
  rem_node(&n->n);
227
  add_tail(&neigh_hash_table[neigh_hash(n->proto, &n->addr)], &n->n);
228
  DBG("Waking up sticky neighbor %I\n", n->addr);
229
  if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING)
230
    n->proto->neigh_notify(n);
231
}
232

  
233
static void
234
neigh_down(neighbor *n)
235
{
236
  DBG("Flushing neighbor %I on %s\n", n->addr, i->name);
237
  rem_node(&n->if_n);
238
  n->iface = NULL;
239
  if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING)
240
    n->proto->neigh_notify(n);
241
  rem_node(&n->n);
242
  if (n->flags & NEF_STICKY)
243
    add_tail(&sticky_neigh_list, &n->n);
244
  else
245
    sl_free(neigh_slab, n);
246
}
247

  
248

  
222 249
/**
223 250
 * neigh_if_up: notify neighbor cache about interface up event
224 251
 * @i: interface in question
......
236 263

  
237 264
  WALK_LIST_DELSAFE(n, next, sticky_neigh_list)
238 265
    if ((scope = if_connected(&n->addr, i)) >= 0)
239
      {
240
	n->iface = i;
241
	n->scope = scope;
242
	add_tail(&i->neighbors, &n->if_n);
243
	rem_node(&n->n);
244
	add_tail(&neigh_hash_table[neigh_hash(n->proto, &n->addr)], &n->n);
245
	DBG("Waking up sticky neighbor %I\n", n->addr);
246
	if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING)
247
	  n->proto->neigh_notify(n);
248
      }
266
      neigh_up(n, i, scope);
249 267
}
250 268

  
251 269
/**
......
263 281
  node *x, *y;
264 282

  
265 283
  WALK_LIST_DELSAFE(x, y, i->neighbors)
266
    {
267
      neighbor *n = SKIP_BACK(neighbor, if_n, x);
268
      DBG("Flushing neighbor %I on %s\n", n->addr, i->name);
269
      rem_node(&n->if_n);
270
      n->iface = NULL;
271
      if (n->proto->neigh_notify && n->proto->core_state != FS_FLUSHING)
272
	n->proto->neigh_notify(n);
273
      rem_node(&n->n);
274
      if (n->flags & NEF_STICKY)
275
	add_tail(&sticky_neigh_list, &n->n);
276
      else
277
	sl_free(neigh_slab, n);
278
    }
284
    neigh_down(SKIP_BACK(neighbor, if_n, x));
279 285
}
280 286

  
281 287
/**
......
286 292
 * All owners of neighbor entries connected to this interface are
287 293
 * notified.
288 294
 */
289

  
290 295
void
291 296
neigh_if_link(struct iface *i)
292 297
{
......
300 305
    }
301 306
}
302 307

  
308
/**
309
 * neigh_ifa_update: notify neighbor cache about interface address add or remove event
310
 * @ifa: interface address in question
311
 *
312
 * Tell the neighbor cache that an address was added or removed.
313
 *
314
 * The neighbor cache wakes up all inactive sticky neighbors with
315
 * addresses belonging to prefixes of the interface belonging to @ifa
316
 * and causes all unreachable neighbors to be flushed.
317
 */
318
void
319
neigh_ifa_update(struct ifa *a)
320
{
321
  struct iface *i = a->iface;
322
  node *x, *y;
323
 
324
  /* Remove all neighbors whose scope has changed */
325
  WALK_LIST_DELSAFE(x, y, i->neighbors)
326
    {
327
      neighbor *n = SKIP_BACK(neighbor, if_n, x);
328
      if (if_connected(&n->addr, i) != n->scope)
329
	neigh_down(n);
330
    }
331

  
332
  /* Wake up all sticky neighbors that are reachable now */
333
  neigh_if_up(i);
334
}
335

  
303 336
static inline void
304 337
neigh_prune_one(neighbor *n)
305 338
{

Also available in: Unified diff