• Ihar Hrachyshka's avatar
    neighbour: update neigh timestamps iff update is effective · 77d71233
    Ihar Hrachyshka authored
    It's a common practice to send gratuitous ARPs after moving an
    IP address to another device to speed up healing of a service. To
    fulfill service availability constraints, the timing of network peers
    updating their caches to point to a new location of an IP address can be
    particularly important.
    
    Sometimes neigh_update calls won't touch neither lladdr nor state, for
    example if an update arrives in locktime interval. The neigh->updated
    value is tested by the protocol specific neigh code, which in turn
    will influence whether NEIGH_UPDATE_F_OVERRIDE gets set in the
    call to neigh_update() or not. As a result, we may effectively ignore
    the update request, bailing out of touching the neigh entry, except that
    we still bump its timestamps inside neigh_update.
    
    This may be a problem for updates arriving in quick succession. For
    example, consider the following scenario:
    
    A service is moved to another device with its IP address. The new device
    sends three gratuitous ARP requests into the network with ~1 seconds
    interval between them. Just before the first request arrives to one of
    network peer nodes, its neigh entry for the IP address transitions from
    STALE to DELAY.  This transition, among other things, updates
    neigh->updated. Once the kernel receives the first gratuitous ARP, it
    ignores it because its arrival time is inside the locktime interval. The
    kernel still bumps neigh->updated. Then the second gratuitous ARP
    request arrives, and it's also ignored because it's still in the (new)
    locktime interval. Same happens for the third request. The node
    eventually heals itself (after delay_first_probe_time seconds since the
    initial transition to DELAY state), but it just wasted some time and
    require a new ARP request/reply round trip. This unfortunate behaviour
    both puts more load on the network, as well as reduces service
    availability.
    
    This patch changes neigh_update so that it bumps neigh->updated (as well
    as neigh->confirmed) only once we are sure that either lladdr or entry
    state will change). In the scenario described above, it means that the
    second gratuitous ARP request will actually update the entry lladdr.
    
    Ideally, we would update the neigh entry on the very first gratuitous
    ARP request. The locktime mechanism is designed to ignore ARP updates in
    a short timeframe after a previous ARP update was honoured by the kernel
    layer. This would require tracking timestamps for state transitions
    separately from timestamps when actual updates are received. This would
    probably involve changes in neighbour struct. Therefore, the patch
    doesn't tackle the issue of the first gratuitous APR ignored, leaving
    it for a follow-up.
    Signed-off-by: default avatarIhar Hrachyshka <ihrachys@redhat.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    77d71233
neighbour.c 79.2 KB