Change 'map ip' to add or insert, rather than just insert. This allows for speedy changes without a remove, making it an atomic operation. So you can add a new queue, change the IP/net, and wait a few seconds before deleting the old one to avoid packet loss during reloads.

This commit is contained in:
Herbert Wolverson 2023-03-21 17:46:51 +00:00
parent 5ba2d2f256
commit f6318d8652
2 changed files with 33 additions and 1 deletions

View File

@ -130,6 +130,38 @@ where
}
}
/// Inserts an entry into a BPF map, or updates an existing entry with
/// the same key.
///
/// Use this sparingly, because it briefly pauses XDP access to the
/// underlying map (through internal locking we can't reach from
/// userland).
///
/// ## Arguments
///
/// * `key` - the key to insert.
/// * `value` - the value to insert.
///
/// Returns Ok if insertion succeeded, a generic error (no details yet)
/// if it fails.
pub(crate) fn insert_or_update(&mut self, key: &mut K, value: &mut V) -> Result<()> {
let key_ptr: *mut K = key;
let val_ptr: *mut V = value;
let err = unsafe {
bpf_map_update_elem(
self.fd,
key_ptr as *mut c_void,
val_ptr as *mut c_void,
BPF_NOEXIST.into(),
)
};
if err != 0 {
Err(Error::msg(format!("Unable to insert into map ({err})")))
} else {
Ok(())
}
}
/// Deletes an entry from the underlying eBPF map.
/// Use this sparingly, it locks the underlying map in the
/// kernel. This can cause *long* delays under heavy load.

View File

@ -34,7 +34,7 @@ pub fn add_ip_to_tc(
let mut key = IpHashKey { prefixlen: ip_to_add.prefix, address: address.0 };
let mut value =
IpHashData { cpu: ip_to_add.cpu, tc_handle: ip_to_add.handle() };
bpf_map.insert(&mut key, &mut value)?;
bpf_map.insert_or_update(&mut key, &mut value)?;
Ok(())
}