Revision acb04cfd

View differences:

nest/route.h
174 174
  ip_addr addr;				/* IP address of host, part of key */
175 175
  ip_addr link;				/* (link-local) IP address of host, used as gw
176 176
					   if host is directly attached */
177
  struct rtable *tab;			/* Dependent table, part of key*/
177
  struct rtable *tab;			/* Dependent table, part of key */
178 178
  struct hostentry *next;		/* Next in hash chain */
179 179
  unsigned hash_key;			/* Hash key */
180 180
  unsigned uc;				/* Use count */
......
507 507
void rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_addr *ll);
508 508

  
509 509
/*
510
 * rta_set_recursive_next_hop() acquires hostentry from hostcache and
511
 * fills rta->hostentry field.  New hostentry has zero use
512
 * count. Cached rta locks its hostentry (increases its use count),
513
 * uncached rta does not lock it. Hostentry with zero use count is
514
 * removed asynchronously during host cache update, therefore it is
515
 * safe to hold such hostentry temorarily. Hostentry holds a lock for
516
 * a 'source' rta, mainly to share multipath nexthops. There is no
517
 * need to hold a lock for hostentry->dep table, because that table
518
 * contains routes responsible for that hostentry, and therefore is
519
 * non-empty if given hostentry has non-zero use count. The protocol
520
 * responsible for routes with recursive next hops should also hold a
521
 * lock for a table governing that routes (argument tab to
522
 * rta_set_recursive_next_hop()).
510
 * rta_set_recursive_next_hop() acquires hostentry from hostcache and fills
511
 * rta->hostentry field.  New hostentry has zero use count. Cached rta locks its
512
 * hostentry (increases its use count), uncached rta does not lock it. Hostentry
513
 * with zero use count is removed asynchronously during host cache update,
514
 * therefore it is safe to hold such hostentry temorarily. Hostentry holds a
515
 * lock for a 'source' rta, mainly to share multipath nexthops.
516
 *
517
 * There is no need to hold a lock for hostentry->dep table, because that table
518
 * contains routes responsible for that hostentry, and therefore is non-empty if
519
 * given hostentry has non-zero use count. If the hostentry has zero use count,
520
 * the entry is removed before dep is referenced.
521
 *
522
 * The protocol responsible for routes with recursive next hops should hold a
523
 * lock for a 'source' table governing that routes (argument tab to
524
 * rta_set_recursive_next_hop()), because its routes reference hostentries
525
 * (through rta) related to the governing table. When all such routes are
526
 * removed, rtas are immediately removed achieving zero uc. Then the 'source'
527
 * table lock could be immediately released, although hostentries may still
528
 * exist - they will be freed together with the 'source' table.
523 529
 */
524 530

  
525 531
static inline void rt_lock_hostentry(struct hostentry *he) { if (he) he->uc++; }
sysdep/linux/netlink.c
239 239
    return 1;
240 240
}
241 241

  
242
static inline ip4_addr rta_get_u32(struct rtattr *a)
243
{ return *(u32 *) RTA_DATA(a); }
244

  
245
static inline ip4_addr rta_get_ip4(struct rtattr *a)
246
{ return ip4_ntoh(*(ip4_addr *) RTA_DATA(a)); }
247

  
248
static inline ip6_addr rta_get_ip6(struct rtattr *a)
249
{ return ip6_ntoh(*(ip6_addr *) RTA_DATA(a)); }
250

  
251

  
242 252
struct rtattr *
243 253
nl_add_attr(struct nlmsghdr *h, uint bufsize, uint code, const void *data, uint dlen)
244 254
{
......
420 430
      return -1;
421 431

  
422 432
    metrics[0] |= 1 << a->rta_type;
423
    metrics[a->rta_type] = *(u32 *)RTA_DATA(a);
433
    metrics[a->rta_type] = rta_get_u32(a);
424 434
  }
425 435

  
426 436
  if (len > 0)
......
456 466
      return;
457 467
    }
458 468
  name = RTA_DATA(a[IFLA_IFNAME]);
459
  memcpy(&mtu, RTA_DATA(a[IFLA_MTU]), sizeof(u32));
469
  mtu = rta_get_u32(a[IFLA_MTU]);
460 470

  
461 471
  ifi = if_find_by_index(i->ifi_index);
462 472
  if (!new)
......
831 841
    }
832 842

  
833 843
  if (a[RTA_OIF])
834
    memcpy(&oif, RTA_DATA(a[RTA_OIF]), sizeof(oif));
844
    oif = rta_get_u32(a[RTA_OIF]);
835 845

  
836 846
  p = nl_table_map[i->rtm_table];	/* Do we know this table? */
837 847
  DBG("KRT: Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, i->rtm_table, i->rtm_protocol, p ? p->p.name : "(none)");
......
965 975
  e->u.krt.src = src;
966 976
  e->u.krt.proto = i->rtm_protocol;
967 977
  e->u.krt.type = i->rtm_type;
978
  e->u.krt.metric = 0;
968 979

  
969 980
  if (a[RTA_PRIORITY])
970
    memcpy(&e->u.krt.metric, RTA_DATA(a[RTA_PRIORITY]), sizeof(e->u.krt.metric));
971
  else
972
    e->u.krt.metric = 0;
981
    e->u.krt.metric = rta_get_u32(a[RTA_PRIORITY]);
973 982

  
974 983
  if (a[RTA_PREFSRC])
975 984
    {
......
1000 1009
      ea->attrs[0].id = EA_KRT_REALM;
1001 1010
      ea->attrs[0].flags = 0;
1002 1011
      ea->attrs[0].type = EAF_TYPE_INT;
1003
      memcpy(&ea->attrs[0].u.data, RTA_DATA(a[RTA_FLOW]), 4);
1012
      ea->attrs[0].u.data = rta_get_u32(a[RTA_FLOW]);
1004 1013
    }
1005 1014

  
1006 1015
  if (a[RTA_METRICS])

Also available in: Unified diff