Skip to content

Commit

Permalink
Use dev + inode to identify/compare netns (istio#1244)
Browse files Browse the repository at this point in the history
* Use dev + ino to identify/compare netns

Signed-off-by: Benjamin Leggett <[email protected]>

* Drop todo

Signed-off-by: Benjamin Leggett <[email protected]>

* This can be copy, it's u64s

Signed-off-by: Benjamin Leggett <[email protected]>

---------

Signed-off-by: Benjamin Leggett <[email protected]>
  • Loading branch information
bleggett authored and antonioberben committed Oct 1, 2024
1 parent 94f263d commit d82ade3
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 11 deletions.
28 changes: 23 additions & 5 deletions src/inpod/netns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ use std::os::fd::OwnedFd;
use std::os::unix::io::AsRawFd;
use std::sync::Arc;

#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
pub struct NetnsID {
pub inode: libc::ino_t,
pub dev: libc::dev_t,
}

// This is similar to netns_rs, but because we know we always have the same netns to revert to,
// we can make it more efficient with less chances of errors.

Expand All @@ -28,7 +34,7 @@ pub struct InpodNetns {
struct NetnsInner {
cur_netns: Arc<OwnedFd>,
netns: OwnedFd,
netns_inode: libc::ino_t,
netns_id: NetnsID,
}

impl InpodNetns {
Expand All @@ -49,22 +55,24 @@ impl InpodNetns {
pub fn new(cur_netns: Arc<OwnedFd>, workload_netns: OwnedFd) -> std::io::Result<Self> {
let res = nix::sys::stat::fstat(workload_netns.as_raw_fd())
.map_err(|e| std::io::Error::from_raw_os_error(e as i32))?;
let netns_inode = res.st_ino;
let inode = res.st_ino;
let dev = res.st_dev;
Ok(InpodNetns {
inner: Arc::new(NetnsInner {
cur_netns,
netns: workload_netns,
netns_inode,
netns_id: NetnsID { inode, dev },
}),
})
}
pub fn workload_netns(&self) -> std::os::fd::BorrowedFd {
use std::os::fd::AsFd;
self.inner.netns.as_fd()
}

// useful for logging / debugging
pub fn workload_inode(&self) -> libc::ino_t {
self.inner.netns_inode
pub fn workload_netns_id(&self) -> NetnsID {
self.inner.netns_id
}

pub fn run<F, T>(&self, f: F) -> std::io::Result<T>
Expand All @@ -85,6 +93,16 @@ impl std::os::unix::io::AsRawFd for InpodNetns {
}
}

impl PartialEq for InpodNetns {
fn eq(&self, other: &Self) -> bool {
// Two netnses can be considered the same if the ino and dev they point to are the same
// (see - cilium, vishvananda/netns, others)
self.inner.netns_id == other.inner.netns_id
}
}

impl Eq for InpodNetns {}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
13 changes: 7 additions & 6 deletions src/inpod/statemanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ use crate::state::WorkloadInfo;

use super::config::InPodConfig;

use super::netns::InpodNetns;
use super::netns::{InpodNetns, NetnsID};
use super::WorkloadUid;

// Note: we can't drain on drop, as drain is async (it waits for the drain to finish).
pub(super) struct WorkloadState {
drain: DrainTrigger,
workload_netns_inode: libc::ino_t,
netns_id: NetnsID,
}

#[derive(Default)]
Expand Down Expand Up @@ -241,7 +241,7 @@ impl WorkloadProxyManagerState {
// check if we have a proxy already
let maybe_existing = self.workload_states.get(workload_uid);
if let Some(existing) = maybe_existing {
if existing.workload_netns_inode != netns.workload_inode() {
if existing.netns_id != netns.workload_netns_id() {
// inodes are different, we have a new netns.
// this can happen when there's a CNI failure (that's unrelated to us) which triggers
// pod sandobx to be re-created with a fresh new netns.
Expand All @@ -257,16 +257,17 @@ impl WorkloadProxyManagerState {
self.admin_handler
.proxy_pending(workload_uid, workload_info);

let workload_netns_id = netns.workload_netns_id();

debug!(
workload=?workload_uid,
workload_info=?workload_info,
inode=?netns.workload_inode(),
netns_id=?workload_netns_id,
"starting proxy",
);

// We create a per workload drain here. If the main loop in WorkloadProxyManager::run drains,
// we drain all these per-workload drains before exiting the loop
let workload_netns_inode = netns.workload_inode();
let (drain_tx, drain_rx) = drain::new();

let proxies = self
Expand Down Expand Up @@ -316,7 +317,7 @@ impl WorkloadProxyManagerState {
workload_uid.clone(),
WorkloadState {
drain: drain_tx,
workload_netns_inode,
netns_id: workload_netns_id,
},
);

Expand Down

0 comments on commit d82ade3

Please sign in to comment.