5 个版本

0.17.6 2024 年 6 月 11 日
0.17.5 2024 年 5 月 30 日
0.17.4 2024 年 5 月 30 日
0.17.3 2024 年 3 月 24 日
0.17.2 2024 年 3 月 24 日

#18模拟

43 次月下载

自定义许可证

1.5MB
29K SLoC

GitHub Actions Workflow Status Crates.io Version Crates.io Total Downloads docs.rs Coveralls

网络控制平面模拟器

这是一个用于 BGP 和 OSPF 路由协议的模拟器。它不模拟 OSI 层 1 到 4。因此,路由器和接口没有 IP 地址,而是使用标识符(RouterId)。此外,模拟器通过全局事件队列交换控制平面消息,而不直接模拟时间。消息不一定反映控制平面消息的序列化和反序列化方式。BGP 和 OSPF 的实现 直接对应于 IETF 的规范。相反,协议被简化(例如,路由器不交换 OSPF Hello 和 BGP Keepalive 包)。

功能

  • 支持的协议
    • BGP
      • 任意路由映射
      • 路由反射
      • 联邦
      • 附加路径
      • 域间拓扑
    • OSPF
      • 多个区域
      • ECMP
      • 虚拟链路
    • 静态路由
    • MPLS / 源路由
  • 可交换事件队列
    • 我们提供默认的 FIFO 队列和基本计时模型。
    • 您可以通过实现 EventQueue 特性来实现您自己的队列。
  • 前缀类型选择
    • 您可以在 Ipv4Prefix 模式下运行 BGP(具有层次化前缀)。但您也可以选择不使用层次结构,并假设前缀没有重叠,或者 BGP 中只有一个前缀。
    • 此选择编码在类型系统中。
    • 编译器可以根据前缀类型应用优化(使用 prefix-trie 用于层次化前缀,一个 HashMap 用于非重叠前缀,以及一个简单的 Option 用于单个前缀)。
  • 通过传递直接消息或使用全局预言机来模拟 OSPF。
  • 提取转发状态并根据它检查属性。
  • 包含来自 TopologyZoo 的拓扑。
  • 将网络配置导出为 Cisco 和 FRR 配置。

示例

以下示例生成了一个包含两个边界路由器(B0B1)、两个路由反射器(R0R1)以及两个外部路由器(E0E1)的网络。这两个路由器都通告前缀 Prefix::from(0),并且所有链路具有相同的权重 1.0

use bgpsim::prelude::*;

// Define the type of the network.
type Prefix = SimplePrefix;           // Use non-overlapping prefixes.
type Queue = BasicEventQueue<Prefix>; // Use a basic FIFO event queue
type Ospf = GlobalOspf;               // Use global OSPF without message passing
type Net = Network<Prefix, Queue, Ospf>;

fn main() -> Result<(), NetworkError> {

    let mut t = Net::default();

    let prefix = Prefix::from(0);

    let e0 = t.add_external_router("E0", 1);
    let b0 = t.add_router("B0");
    let r0 = t.add_router("R0");
    let r1 = t.add_router("R1");
    let b1 = t.add_router("B1");
    let e1 = t.add_external_router("E1", 2);

    t.add_link(e0, b0);
    t.add_link(b0, r0);
    t.add_link(r0, r1);
    t.add_link(r1, b1);
    t.add_link(b1, e1);

    t.set_link_weight(b0, r0, 1.0)?;
    t.set_link_weight(r0, b0, 1.0)?;
    t.set_link_weight(r0, r1, 1.0)?;
    t.set_link_weight(r1, r0, 1.0)?;
    t.set_link_weight(r1, b1, 1.0)?;
    t.set_link_weight(b1, r1, 1.0)?;
    t.set_bgp_session(e0, b0, Some(BgpSessionType::EBgp))?;
    t.set_bgp_session(r0, b0, Some(BgpSessionType::IBgpClient))?;
    t.set_bgp_session(r0, r1, Some(BgpSessionType::IBgpPeer))?;
    t.set_bgp_session(r1, b1, Some(BgpSessionType::IBgpClient))?;
    t.set_bgp_session(e1, b1, Some(BgpSessionType::EBgp))?;

    // advertise the same prefix on both routers
    t.advertise_external_route(e0, prefix, &[1, 2, 3], None, None)?;
    t.advertise_external_route(e1, prefix, &[2, 3], None, None)?;

    // get the forwarding state
    let mut fw_state = t.get_forwarding_state();

    // check that all routes are correct
    assert_eq!(fw_state.get_paths(b0, prefix)?, vec![vec![b0, r0, r1, b1, e1]]);
    assert_eq!(fw_state.get_paths(r0, prefix)?, vec![vec![r0, r1, b1, e1]]);
    assert_eq!(fw_state.get_paths(r1, prefix)?, vec![vec![r1, b1, e1]]);
    assert_eq!(fw_state.get_paths(b1, prefix)?, vec![vec![b1, e1]]);

    Ok(())
}

您可以使用 net! 宏创建相同的网络。

use bgpsim::prelude::*;

fn main() -> Result<(), NetworkError> {
    let (t, (e0, b0, r0, r1, b1, e1)) = net! {
        Prefix = Ipv4Prefix;
        Ospf = GlobalOspf;
        links = {
            b0 -> r0: 1;
            b1 -> r1: 1;
            r0 -> r1: 1;
        };
        sessions = {
            e0!(1) -> b0;
            e1!(2) -> b1;
            r0 -> r1;
            r0 -> b0: client;
            r1 -> b1: client;
        };
        routes = {
            e0 -> "100.0.0.0/8" as {path: [1, 2, 3]};
            e1 -> "100.0.0.0/8" as {path: [2, 3]};
        };
        return (e0, b0, r0, r1, b1, e1)
    };

    // get the forwarding state
    let mut fw_state = t.get_forwarding_state();

    // check that all routes are correct
    assert_eq!(fw_state.get_paths(b0, prefix!("100.0.0.0/8" as))?, vec![vec![b0, r0, r1, b1, e1]]);
    assert_eq!(fw_state.get_paths(r0, prefix!("100.20.1.3/32" as))?, vec![vec![r0, r1, b1, e1]]);
    assert_eq!(fw_state.get_paths(r1, prefix!("100.2.0.0/16" as))?, vec![vec![r1, b1, e1]]);
    assert_eq!(fw_state.get_paths(b1, prefix!("100.0.0.0/24" as))?, vec![vec![b1, e1]]);

    Ok(())
}

此库包含来自 TopologyZoo 的网络以及方便的构建函数,以便快速生成随机配置。注意,这需要 topology_zoorand 功能。

use bgpsim::prelude::*;
use bgpsim::builder::*;

type Prefix = SimplePrefix;           // Use non-overlapping prefixes.
type Queue = BasicEventQueue<Prefix>; // Use a basic FIFO event queue
type Ospf = GlobalOspf;               // Use global OSPF without message passing
type Net = Network<Prefix, Queue, Ospf>;

fn main() -> Result<(), NetworkError> {

    // create the Abilene network
    let mut net: Net = TopologyZoo::Abilene.build(Queue::new());
    // Create 5 random external routers
    net.build_external_routers(extend_to_k_external_routers, 5)?;
    // Assign random link weights between 10 and 100.
    net.build_link_weights(random_link_weight, (10.0, 100.0))?;
    // Generate an iBGP full-mesh topology.
    net.build_ibgp_full_mesh()?;
    // Generate all eBGP sessions
    net.build_ebgp_sessions()?;
    // Generate route-maps to implement Gao-Rexford routing policies, with probability 20% that
    // an external network will be treated as a customer, 30% that it will be treated as peer,
    // and 50% that it will be a provider.
    let _peer_types = net.build_gao_rexford_policies(GaoRexfordPeerType::random, (0.2, 0.3))?;

    Ok(())
}

免责声明

此库是一个研究项目。它最初是为 SGICOMM'21 论文“Snowcap: Synthesizing Network-Wide Configuration Updates”编写的。如果您正在使用此项目,请引用我们。

@INPROCEEDINGS{schneider2021snowcap,
  isbn = {978-1-4503-8383-7},
  copyright = {In Copyright - Non-Commercial Use Permitted},
  doi = {10.3929/ethz-b-000491508},
  year = {2021-08},
  booktitle = {Proceedings of the 2021 ACM SIGCOMM Conference},
  type = {Conference Paper},
  institution = {EC},
  author = {Schneider, Tibor and Birkner, Rüdiger and Vanbever, Laurent},
  keywords = {Network analysis; Configuration; Migration},
  language = {en},
  address = {New York, NY},
  publisher = {Association for Computing Machinery},
  title = {Snowcap: Synthesizing Network-Wide Configuration Updates},
  PAGES = {33 - 49},
  Note = {ACM SIGCOMM 2021 Conference; Conference Location: Online; Conference Date: August 23-27, 2021}
}

依赖项

~4.5–7MB
~106K SLoC