Commit e35ef181 authored by Martin Mares's avatar Martin Mares
Browse files

o The if_change_too_big_p change was too high-spirited. Fixed.

o  Introduced if_find_by_index()
o  Recognizing two types of interface updates: full update (starting with
   if_start_update(), ending with if_end_update(), guaranteed to see
   all existing interfaces) and a partial update (only if_update(),
   usually due to asynchronous interface notifications).
parent bcbd8cc3
Loading
Loading
Loading
Loading
+28 −9
Original line number Diff line number Diff line
@@ -231,8 +231,6 @@ if_dump_all(void)
static inline int
if_change_too_big_p(struct iface *i, struct iface *j)
{
  if ((i->flags ^ j->flags) & IF_UP)	/* Going up/down is always OK */
    return 0;
  if (!ipa_equal(i->ip, j->ip) ||	/* Address change isn't */
      !ipa_equal(i->prefix, j->prefix) ||
      i->pxlen != j->pxlen ||
@@ -310,16 +308,19 @@ if_update(struct iface *new)
	if (if_change_too_big_p(i, new)) /* Changed a lot, convert it to down/up */
	  {
	    DBG("Interface %s changed too much -- forcing down/up transition\n", i->name);
	    if (i->flags & IF_UP)
	      {
		i->flags &= ~IF_UP;
		if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, i, NULL);
	      }
	    rem_node(&i->n);
	    goto newif;
	  }
	c = if_changed(i, new);
	if_copy(i, new);		/* Even if c==0 as we might need to update i->index et al. */
	i->flags |= IF_UPDATED;
	if (c)
	  if_notify_change(c, i, new);
	if_copy(i, new);		/* Even if c==0 as we might need to update i->index et al. */
	i->flags |= IF_UPDATED;
	return;
      }

@@ -332,6 +333,15 @@ newif:
		   | IF_CHANGE_FLAGS | IF_CHANGE_MTU, NULL, i);
}

void
if_start_update(void)
{
  struct iface *i;

  WALK_LIST(i, iface_list)
    i->flags &= ~IF_UPDATED;
}

void
if_end_update(void)
{
@@ -341,9 +351,7 @@ if_end_update(void)
    auto_router_id();

  WALK_LIST(i, iface_list)
    if (i->flags & IF_UPDATED)
      i->flags &= ~IF_UPDATED;
    else
    if (!(i->flags & IF_UPDATED))
      {
	memcpy(&j, i, sizeof(struct iface));
	i->flags = (i->flags & ~(IF_LINK_UP | IF_UP)) | IF_ADMIN_DOWN;
@@ -364,6 +372,17 @@ if_feed_baby(struct proto *p)
    p->if_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i, NULL);
}

struct iface *
if_find_by_index(unsigned idx)
{
  struct iface *i;

  WALK_LIST(i, iface_list)
    if (i->index == idx)
      return i;
  return NULL;
}

static void
auto_router_id(void)			/* FIXME: What if we run IPv6??? */
{
+2 −0
Original line number Diff line number Diff line
@@ -53,8 +53,10 @@ void if_init(void);
void if_dump(struct iface *);
void if_dump_all(void);
void if_update(struct iface *);
void if_start_update(void);
void if_end_update(void);
void if_feed_baby(struct proto *);
struct iface *if_find_by_index(unsigned);

/*
 *	Neighbor Cache. We hold (direct neighbor, protocol) pairs we've seen
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ scan_ifs(struct ifreq *r, int cnt)
  ip_addr netmask;
  int l;

  if_start_update();
  for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
    {
      bzero(&i, sizeof(i));