diff --git a/bins/packages/vector/files/vector.yaml b/bins/packages/vector/files/vector.yaml index 397193aa1..ee0efbae5 100644 --- a/bins/packages/vector/files/vector.yaml +++ b/bins/packages/vector/files/vector.yaml @@ -14,6 +14,7 @@ sources: - b-* - br-* - dumdum + - mydumdum - dummy* - tozos* filesystem: diff --git a/cmds/modules/networkd/main.go b/cmds/modules/networkd/main.go index 42d3e3228..45f6c374d 100644 --- a/cmds/modules/networkd/main.go +++ b/cmds/modules/networkd/main.go @@ -10,6 +10,7 @@ import ( "github.com/pkg/errors" "github.com/threefoldtech/zos/pkg/environment" "github.com/threefoldtech/zos/pkg/network/dhcp" + "github.com/threefoldtech/zos/pkg/network/mycelium" "github.com/threefoldtech/zos/pkg/network/public" "github.com/threefoldtech/zos/pkg/network/types" "github.com/threefoldtech/zos/pkg/zinit" @@ -110,47 +111,25 @@ func action(cli *cli.Context) error { if err := dmz.Create(ctx); err != nil { return errors.Wrap(err, "failed to create ndmz") } - log.Debug().Msg("starting yggdrasil") - yggNamespace := dmz.Namespace() + + namespace := dmz.Namespace() if public.HasPublicSetup() { - yggNamespace = public.PublicNamespace + namespace = public.PublicNamespace } - yggNs, err := yggdrasil.NewYggdrasilNamespace(yggNamespace) + log.Debug().Msg("starting yggdrasil") + ygg, err := setupYgg(ctx, namespace, dmz.Namespace(), identity.PrivateKey(cli.Context)) if err != nil { - return errors.Wrap(err, "failed to create yggdrasil namespace") + return err } - ygg, err := yggdrasil.EnsureYggdrasil(ctx, identity.PrivateKey(cli.Context), yggNs) + log.Debug().Msg("starting mycelium") + mycelium, err := setupMycelium(ctx, namespace, dmz.Namespace(), identity.PrivateKey(cli.Context)) if err != nil { - return errors.Wrap(err, "failed to start yggdrasil") - } - - if public.HasPublicSetup() { - // if yggdrasil is living inside public namespace - // we still need to setup ndmz to also have yggdrasil but we set the yggdrasil interface - // a different Ip that lives inside the yggdrasil range. - dmzYgg, err := yggdrasil.NewYggdrasilNamespace(dmz.Namespace()) - if err != nil { - return errors.Wrap(err, "failed to setup ygg for dmz namespace") - } - - ip, err := ygg.SubnetFor([]byte(fmt.Sprintf("ygg:%s", dmz.Namespace()))) - if err != nil { - return errors.Wrap(err, "failed to calculate ip for ygg inside dmz") - } - - gw, err := ygg.Gateway() - if err != nil { - return err - } - - if err := dmzYgg.SetYggIP(ip, gw.IP); err != nil { - return errors.Wrap(err, "failed to set yggdrasil ip for dmz") - } + return err } - networker, err := network.NewNetworker(identity, dmz, ygg) + networker, err := network.NewNetworker(identity, dmz, ygg, mycelium) if err != nil { return errors.Wrap(err, "error creating network manager") } @@ -164,7 +143,6 @@ func action(cli *cli.Context) error { } func startZBusServer(ctx context.Context, broker string, networker pkg.Networker) error { - server, err := zbus.NewRedisServer(module, broker, 1) if err != nil { log.Error().Err(err).Msgf("fail to connect to message broker server") @@ -187,7 +165,7 @@ func startZBusServer(ctx context.Context, broker string, networker pkg.Networker func waitYggdrasilBin() { log.Info().Msg("wait for yggdrasil binary to be available") bo := backoff.NewExponentialBackOff() - bo.MaxElapsedTime = 0 //forever + bo.MaxElapsedTime = 0 // forever _ = backoff.RetryNotify(func() error { _, err := exec.LookPath("yggdrasil") return err @@ -212,3 +190,82 @@ func migrateOlderDHCPService() error { return nil } + +func setupYgg(ctx context.Context, namespace, dmzNs string, privateKey []byte) (ygg *yggdrasil.YggServer, err error) { + yggNs, err := yggdrasil.NewYggdrasilNamespace(namespace) + if err != nil { + return ygg, errors.Wrap(err, "failed to create yggdrasil namespace") + } + + ygg, err = yggdrasil.EnsureYggdrasil(ctx, privateKey, yggNs) + if err != nil { + return ygg, errors.Wrap(err, "failed to start yggdrasil") + } + + if public.HasPublicSetup() { + // if yggdrasil is living inside public namespace + // we still need to setup ndmz to also have yggdrasil but we set the yggdrasil interface + // a different Ip that lives inside the yggdrasil range. + dmzYgg, err := yggdrasil.NewYggdrasilNamespace(dmzNs) + if err != nil { + return ygg, errors.Wrap(err, "failed to setup ygg for dmz namespace") + } + + ip, err := ygg.SubnetFor([]byte(fmt.Sprintf("ygg:%s", dmzNs))) + if err != nil { + return ygg, errors.Wrap(err, "failed to calculate ip for ygg inside dmz") + } + + gw, err := ygg.Gateway() + if err != nil { + return ygg, err + } + + if err := dmzYgg.SetYggIP(ip, gw.IP); err != nil { + return ygg, errors.Wrap(err, "failed to set yggdrasil ip for dmz") + } + } + return +} + +func setupMycelium(ctx context.Context, namespace, dmzNs string, privateKey []byte) (myc *mycelium.MyceliumServer, err error) { + myNs, err := mycelium.NewMyNamespace(namespace) + if err != nil { + return myc, errors.Wrap(err, "failed to create mycelium namespace") + } + + myc, err = mycelium.EnsureMycelium(ctx, privateKey, myNs) + if err != nil { + return myc, errors.Wrap(err, "failed to start mycelium") + } + + if public.HasPublicSetup() { + // if mycelium is living inside public namespace + // we still need to setup ndmz to also have mycelium but we set the mycelium interface + // a different Ip that lives inside the mycelium range. + dmzMy, err := mycelium.NewMyNamespace(dmzNs) + if err != nil { + return myc, errors.Wrap(err, "failed to setup mycelium for dmz namespace") + } + + inspcet, err := myc.InspectMycelium() + if err != nil { + return myc, err + } + + ip, err := inspcet.IPFor([]byte(fmt.Sprintf("my:%s", dmzNs))) + if err != nil { + return myc, errors.Wrap(err, "failed to calculate ip for mycelium inside dmz") + } + + gw, err := inspcet.Gateway() + if err != nil { + return myc, err + } + + if err := dmzMy.SetMyIP(ip, gw.IP); err != nil { + return myc, errors.Wrap(err, "failed to set mycelium ip for dmz") + } + } + return +} diff --git a/docs/architecture/decisions/0009-mycelium.md b/docs/architecture/decisions/0009-mycelium-for-workloads.md similarity index 100% rename from docs/architecture/decisions/0009-mycelium.md rename to docs/architecture/decisions/0009-mycelium-for-workloads.md diff --git a/docs/architecture/decisions/0010-mycelium.md b/docs/architecture/decisions/0010-mycelium.md new file mode 100644 index 000000000..d24ceee25 --- /dev/null +++ b/docs/architecture/decisions/0010-mycelium.md @@ -0,0 +1,19 @@ +# 1. Mycelium + +Date: 2024-05-29 + +## Status + +Accepted + +## Context + +Support mycelium network for zdbs and zos host to get flists over mycelium + +## Decision + +Integrate mycelium in zos and allow zos host to have mycelium IPs, mount flists over mycelium, and support mycelium on zdbs + +## Consequences + +Using mycelium IP is optional. Old clients should work normally without breakage. diff --git a/go.mod b/go.mod index 48c7b0e84..b9a2910c7 100644 --- a/go.mod +++ b/go.mod @@ -115,6 +115,7 @@ require ( github.com/moby/sys/mountinfo v0.6.2 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nsf/termbox-go v1.1.1 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect github.com/onsi/ginkgo v1.16.4 // indirect github.com/onsi/gomega v1.16.0 // indirect github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect diff --git a/go.sum b/go.sum index d0051cc1a..2d5e7ab3c 100644 --- a/go.sum +++ b/go.sum @@ -433,6 +433,8 @@ github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpo github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= diff --git a/pkg/capacity/pci/pci.ids b/pkg/capacity/pci/pci.ids index df152a4e9..4f7035c92 100644 --- a/pkg/capacity/pci/pci.ids +++ b/pkg/capacity/pci/pci.ids @@ -1,8 +1,8 @@ # # List of PCI ID's # -# Version: 2024.05.14 -# Date: 2024-05-14 03:15:02 +# Version: 2024.05.31 +# Date: 2024-05-31 03:15:02 # # Maintained by Albert Pool, Martin Mares, and other volunteers from # the PCI ID Project at https://pci-ids.ucw.cz/. @@ -104,6 +104,17 @@ 025e d81d NVMe DC SSD E1.L 9.5mm [D5-P5336] 0b70 NVMe DC SSD [Yorktown controller] 2b59 NVMe DC SSD [Atomos Prime] + 025e 0008 NVMe DC SSD U.2-SFF 15mm [D7-PS1010] + 025e 0019 NVMe DC SSD E3.S-1T 7.5mm [D7-PS1010] + 025e 0108 NVMe DC SSD U.2-SFF 15mm [D7-PS1030] + 025e 0119 NVMe DC SSD E3.S-1T 7.5mm [D7-PS1030] + 108e 48a0 NVMe DC SSD U.2-SFF 15mm 3.84TB [D7-PS1010 Custom] + 108e 48a1 NVMe DC SSD U.2-SFF 15mm 7.68TB [D7-PS1010 Custom] + 108e 48a2 NVMe DC SSD U.2-SFF 15mm 15.36TB [D7-PS1010 Custom] + 108e 48a3 NVMe DC SSD Add-In-Card [D7-PS1030 Custom] + 108e 48a4 NVMe DC SSD E3.S-1T 7.5mm 3.84TB [D7-PS1010 Custom] + 108e 48a5 NVMe DC SSD E3.S-1T 7.5mm 7.68TB [D7-PS1010 Custom] + 108e 48a6 NVMe DC SSD E3.S-1T 7.5mm 15.36TB [D7-PS1010 Custom] f1ab P41 Plus NVMe SSD (DRAM-less) [Echo Harbor] f1ac P44 Pro NVMe SSD [Hollywood Beach] 0270 Hauppauge computer works Inc. (Wrong ID) @@ -1082,6 +1093,12 @@ 10e4 MegaRAID 12GSAS/PCIe Unsupported SAS38xx 10e5 MegaRAID 12GSAS/PCIe SAS38xx 10e6 MegaRAID 12GSAS/PCIe Secure SAS38xx + 1000 04d9 3808N iMR ROMB + 1000 04da 3808N iMR ROMB + 1000 04db 3808N iMR ROMB + 1000 04dc 3808N iMR ROMB + 1000 04dd 3808N iMR ROMB + 1000 40d8 MegaRAID 9524-8i 1000 40e0 MegaRAID 9540-2M2 1028 2172 PERC H355 Adapter 1028 2173 PERC H355 Front @@ -1249,7 +1266,7 @@ 103c 8b17 ProBook 445 G9/455 G9 [Ryzen 7 Integrated Radeon GPU] 15ff Fenghuang [Zhongshan Subor Z+] 1607 Arden - 1636 Renoir [Radeon RX Vega 6 (Ryzen 4000/5000 Mobile Series)] + 1636 Renoir [Radeon Vega Series / Radeon Vega Mobile Series] 1637 Renoir Radeon High Definition Audio Controller 1638 Cezanne [Radeon Vega Series / Radeon Vega Mobile Series] 1043 16c2 Radeon Vega 8 @@ -4022,10 +4039,12 @@ 7448 Navi 31 [Radeon Pro W7900] 744c Navi 31 [Radeon RX 7900 XT/7900 XTX/7900M] 1002 0e3b RX 7900 GRE [XFX] + 1849 5304 Radeon RX 7900 XTX 1da2 471e PULSE RX 7900 XTX 1da2 e471 NITRO+ RX 7900 XTX Vapor-X 1eae 7901 RX-79XMERCB9 [SPEEDSTER MERC 310 RX 7900 XTX] 745e Navi 31 [Radeon Pro W7800] + 7460 7460 Navi32 GL-XL [AMD Radeon PRO V710] 7470 Navi 32 [Radeon PRO W7700] 747e Navi 32 [Radeon RX 7700 XT / 7800 XT] 7480 Navi 33 [Radeon RX 7700S/7600/7600S/7600M XT/PRO W7600] @@ -5460,10 +5479,12 @@ 1849 43c8 Fatal1ty X370 Professional Gaming 43b6 X399 Series Chipset SATA Controller 43b7 300 Series Chipset SATA Controller + 43b8 A320 Chipset SATA Controller [AHCI mode] 43b9 X370 Series Chipset USB 3.1 xHCI Controller 1849 43d0 Fatal1ty X370 Professional Gaming 43ba X399 Series Chipset USB 3.1 xHCI Controller 43bb 300 Series Chipset USB 3.1 xHCI Controller + 43bc A320 USB 3.1 XHCI Host Controller 43c6 400 Series Chipset PCIe Bridge 43c7 400 Series Chipset PCIe Port 43c8 400 Series Chipset SATA Controller @@ -12959,6 +12980,8 @@ 2296 Tegra PCIe Endpoint Virtual Network 22a3 GH100 [H100 NVSwitch] 22ba AD102 High Definition Audio Controller + 22bc AD104 High Definition Audio Controller + 22bd AD106M High Definition Audio Controller 2302 GH100 2313 GH100 [H100 CNX] 2321 GH100 [H100L 94GB] @@ -13080,6 +13103,7 @@ 2681 AD102 [RTX TITAN Ada] 2684 AD102 [GeForce RTX 4090] 2685 AD102 [GeForce RTX 4090 D] + 2689 AD102 [GeForce RTX 4070 Ti SUPER] 26b1 AD102GL [RTX 6000 Ada Generation] 26b2 AD102GL [RTX 5000 Ada Generation] 26b3 AD102GL [RTX 5880 Ada Generation] @@ -16238,7 +16262,9 @@ 11ae Aztech System Ltd 11af Avid Technology Inc. 0001 Cinema + ee21 Digidesign DSP Farm ee40 Digidesign Audiomedia III + ee60 Digidesign SampleCell II / II Plus 11b0 V3 Semiconductor Inc. 0002 V300PSC 0292 V292PBC [Am29030/40 Bridge] @@ -17445,7 +17471,8 @@ 10a9 8002 Acenic Gigabit Ethernet 12ae 0002 Gigabit Ethernet-T (3C986-T) 00fa Farallon PN9100-T Gigabit Ethernet -12af TDK USA Corp +12af TDK Corporation + 5831 GBDriver GX1 x2 NVMe SSD Controller (DRAM-less) 12b0 Jorge Scientific Corp 12b1 GammaLink 12b2 General Signal Networks @@ -18916,6 +18943,9 @@ 580b Secure Flash Controller (Xenon) 580d System Management Controller (Xenon) 5811 Xenos GPU (Xenon) + 5821 Xenos GPU (Zephyr/Falcon) + 5831 Xenos GPU (Jasper) + 5841 Xenos GPU (Slim) 1415 Oxford Semiconductor Ltd 8401 OX9162 Mode 1 (8-bit bus) 8403 OX9162 Mode 0 (parallel port) @@ -19859,7 +19889,7 @@ 144d a801 SM963 2.5" NVMe PCIe SSD a806 NVMe SSD SM0032L a808 NVMe SSD Controller SM981/PM981/PM983 - 144d a801 SSD 970 EVO/PRO + 144d a801 Samsung SSD 970 EVO Plus 1TB 1d49 403b Thinksystem U.2 PM983 NVMe SSD a809 NVMe SSD Controller 980 (DRAM-less) a80a NVMe SSD Controller PM9A1/PM9A3/980PRO @@ -19886,7 +19916,7 @@ # Actually 88SS1322 according to techpowerup a80b NVMe SSD Controller PM9B1 (DRAM-less) a80c NVMe SSD Controller S4LV008[Pascal] - a80d NVMe SSD Controller PM9C1a + a80d NVMe SSD Controller PM9C1a (DRAM-less) a820 NVMe SSD Controller 171X 1028 1f95 Express Flash NVMe XS1715 SSD 400GB 1028 1f96 Express Flash NVMe XS1715 SSD 800GB @@ -20844,6 +20874,7 @@ 14e4 5250 NetXtreme-E BCM57504 4x25G KR Mezz 14e4 5425 NetXtreme-E Quad-port 25G SFP28 Ethernet OCP 3.0 Adapter (BCM957504-N425G) 14e4 d142 NetXtreme-E P425D BCM57504 4x25G SFP28 PCIE + 1590 0420 HPE Ethernet 25/50Gb 2-port 6310C Adapter 1752 BCM57502 NetXtreme-E 10Gb/25Gb/40Gb/50Gb Ethernet 1760 BCM57608 10Gb/25Gb/50Gb/100Gb/200Gb/400Gb Ethernet 14e4 d125 BCM57608 2x200G PCIe Ethernet NIC @@ -21908,11 +21939,13 @@ 0262 MT27710 [ConnectX-4 Lx Programmable] EN 0263 MT27710 [ConnectX-4 Lx Programmable Virtual Function] EN 0264 Innova-2 Flex Burn image - 0270 Spectrum-4L, Flash recovery mode + 0270 Spectrum-5 in Flash Recovery Mode 0271 Spectrum-4L, RMA - 0274 Spectrum-4C, Flash recovery mode + 0274 Spectrum-6 in Flash Recovery Mode 0275 Spectrum-4C RMA 0277 Spectrum-4TOR RMA + 0278 Quantum-4 in Flash Recovery Mode + 0279 Quantum-4 RMA 0281 NPS-600 Flash Recovery 0282 ArcusE Flash recovery 0283 ArcusE RMA @@ -22132,6 +22165,7 @@ d2f2 Quantum-2 NDR (400Gbps) switch d2f4 Quantum-3 d2f6 Quantum-3CPO + d2f8 Quantum-4 15b4 CCI/TRIAD 15b5 Cimetrics Inc 15b6 Texas Memory Systems Inc @@ -24087,6 +24121,8 @@ 1942 ClearSpeed Technology plc e511 Advance X620 accelerator card e521 Advance e620 accelerator card +1945 MERA + 6200 PXI/PXIe measurement module 1947 C-guys, Inc. 4743 CG200 Dual SD/SDIO Host controller device 1948 Alpha Networks Inc. @@ -24907,6 +24943,7 @@ 1028 2113 BOSS-N1 Modular 1028 2151 BOSS-N1 Modular ET 1028 2196 ROR-N1 + 1028 2286 BOSS-N1 DC-MHS 1b4b 2241 Santa Cruz NVMe Host Adapter 1b96 4000 WD_BLACK AN1500 NVMe SSD 1d49 0306 ThinkSystem M.2 NVMe 2-Bay RAID Enablement Kit @@ -24960,6 +24997,21 @@ # 2xHDMI and 2xHD-SDI inputs e5f4 MPEG2 and H264 Encoder-Transcoder f1c4 Dual ASI-RX/TX-CI card +1b5e STAR-Dundee Ltd. + 0001 SpaceWire PCI Mk2 + 0002 SpaceWire PCIe Mk1 + 0003 SpaceWire cPCI Mk2 + 0004 SpaceWire PXI Recorder Mk1 + 0005 SpaceWire PXI Interface Mk1 + 0006 SpaceWire PXI Interface Mk1 with RMAP Target + 0008 SpaceWire PXI Router Mk1 + 000b SpaceWire PXI Interface Mk2 + 000c SpaceWire PXI Interface Mk2 with RMAP Target + 000d SpaceWire PXI Router Mk2 + 000e SpaceWire PXI Recorder Mk2 + 0100 STAR-Ultra PCIe + 0102 STAR-Ultra Single-Lane Router + 0200 SpaceWire PCIe Mk2 1b61 Byd Precision Manufacture Co.,Ltd 1b66 DELTACAST 0007 DELTA-3G-elp-d @@ -25121,11 +25173,14 @@ 1bb1 0179 Nytro 5360S - E3.S # Nytro 5360S (Rocinante Single Port) TCG - E3.S 1bb1 0180 Nytro 5360S TCG - E3.S +# Nytro 5060H (Rocinante High Performance) non-SED + 1bb1 0181 Nytro 5060H 1bb1 01a1 Nytro XP7102 5012 FireCuda/IronWolf 510 SSD 5013 BarraCuda Q5 NVMe SSD (DRAM-less) 5016 FireCuda 520/IronWolf 525 SSD 5018 FireCuda 530 SSD + 5019 BarraCuda PCIe SSD (DRAM-less) # 2TB 5021 FireCuda 520 SSD # 1TB @@ -25315,6 +25370,7 @@ 0023 Ultrastar SN200 Series NVMe SSD 1c58 8823 Ultrastar Memory (ME200) 1c5c SK hynix + 1069 PCB01 NVMe Solid State Drive 1282 PC300 NVMe Solid State Drive 128GB 1283 PC300 NVMe Solid State Drive 256GB 1284 PC300 NVMe Solid State Drive 512GB @@ -25525,6 +25581,7 @@ 5762 FALCON, GAMMIX S41, SPECTRIX S40G NVMe SSD (DRAM-less) 5763 XPG GAMMIX S5 NVMe SSD (DRAM-less) 5766 XPG GAMMIXS1 1L, XPG GAMMIX S5, LEGEND 710 / 740, SWORDFISH NVMe SSD (DRAM-less) + 5772 LEGEND 850 LITE NVMe SSD (DRAM-less) 612a LEGEND 750 NVMe SSD (DRAM-less) 613a ATOM 50, LEGEND 840 NVMe SSD (DRAM-less) 621a LEGEND 850 NVMe SSD (DRAM-less) @@ -25565,6 +25622,7 @@ 6304 AM630 PCIe 4.0 NVMe SSD 1024GB 6a02 AM6A0 PCIe 4.0 NVMe SSD 256GB 6a03 RPETJ512MKP1QDQ PCIe 4.0 NVMe SSD 512GB (DRAM-less) + 6a13 RPJYJ512MKN1QWQ PCIe 4.0 NVMe SSD 512GB (DRAM-less) 6a14 RPEYJ1T24MKN2QWY PCIe 4.0 NVMe SSD 1024GB (DRAM-less) 8030 NVMe SSD Controller UH8X2X/UH7X2X series 1cc4 1122 NVMe SSD UH812a U.2 1.92TB @@ -25662,7 +25720,7 @@ 071a KX-5000/KX-6000/KX-6000G/KH-40000 PCI Express Root Port 071b KX-5000/KX-6000/KX-6000G/KH-40000/KX-7000 PCI Express Root Port 071c KX-5000/KX-6000/KX-6000G/KH-40000/KX-7000 PCI Express Root Port - 071d KX-5000/KX-6000/KX-6000G/KH-40000 PCI Express Root Port + 071d KX-5000/KX-6000/KX-6000G/KH-40000/KX-7000 PCI Express Root Port 071e KX-5000/KX-6000/KX-6000G/KH-40000/KX-7000 PCI Express Root Port 071f ZX-200 Upstream Port of PCI Express Switch 0720 ZX-200 PCIE RC6 controller @@ -25851,6 +25909,9 @@ 1024 AR-TK242 [2x10GbE Packet Capture Device] 1025 AR-TK242-FX2 [2x100GbE Gen5 Packet Capture Device] 1026 AR-TK242-FX2 [1x200GbE Gen5 Packet Capture Device] + 1027 AR-P2P-DBG [P2P Debug Function] + 1028 AR-P2P-ATR [P2P Actor Function] + 1029 AR-P2P-UTL [P2P Utility Function] 4200 A5PL-E1-10GETI [10 GbE Ethernet Traffic Instrument] 1d72 Xiaomi 1d78 DERA Storage @@ -25979,6 +26040,7 @@ 1062 Lexar NM710 NVME SSD 1160 FORESEE P900 BGA NVMe SSD (DRAM-less) 1202 Lexar NM610 PRO NVME SSD (DRAM-less) + 12e4 ORCA 4836 Series eSSD 1602 Lexar NM790 NVME SSD (DRAM-less) 1d97 Lexar NM620 NVME SSD (DRAM-less) 2263 SM2263EN/SM2263XT-based OEM NVME SSD (DRAM-less) @@ -26058,6 +26120,9 @@ 1dbe 2006 Dongting-N2 DC SSD U.2 7680GB 1dbe 3001 Donghu-Z2 DC ZNS SSD U.2 4000GB 1dbe 3002 Donghu-Z2 DC ZNS SSD U.2 8000GB + 5666 NVMe SSD Controller IG5666 + 5668 NVMe SSD Controller IG5668 + 5669 NVMe SSD Controller IG5669 [Tacoma] 1dbf Guizhou Huaxintong Semiconductor Technology Co., Ltd 0401 StarDragon4800 PCI Express Root Port 1dc2 Alco Digital Devices Limited @@ -26410,6 +26475,7 @@ 1df8 d100 M.2 NVMe SSD 1df8 d201 M.2 NVMe SSD 1df8 d600 M.2 NVMe SSD +1dfa Astera Labs, Inc. 1dfc JSC NT-COM 1181 TDM 8 Port E1/T1/J1 Adapter 1e0d SambaNova Systems, Inc @@ -26595,10 +26661,12 @@ 1e3b 0069 Enterprise NVMe SSD U.2 3.20TB (R5301D) 1e3b 006c Enterprise NVMe SSD U.2 1.92TB (R5101) 1e3b 006d Enterprise NVMe SSD U.2 1.60TB (J5301) - 1e3b 00b9 Enterprise NVMe SSD U.2 QDP 25.60TB (R5300) - 1e3b 00be Enterprise NVMe SSD U.2 QDP 30.72TB (R5100) - 1e3b 00c1 Enterprise NVMe SSD U.2 QDP 25.60TB (R5300D) - 1e3b 00c4 Enterprise NVMe SSD U.2 QDP 30.72TB (R5100D) + 1e3b 00b9 Enterprise NVMe SSD U.2 ODP 25.60TB (R5301)/(J5301) + 1e3b 00be Enterprise NVMe SSD U.2 ODP 30.72TB (R5101)/(J5101) + 1e3b 00c1 Enterprise NVMe SSD U.2 ODP 25.60TB (R5301D)/(J5301D) + 1e3b 00c4 Enterprise NVMe SSD U.2 ODP 30.72TB (R5101D)/(J5101D) + 1e3b 00c7 Enterprise NVMe SSD U.2 ODP 25.60TB (J5300) + 1e3b 00c8 Enterprise NVMe SSD U.2 ODP 30.72TB (J5100) 1e3b 00c9 Enterprise NVMe SSD U.2 ODP 15.36TB (J5001) 1e3b 00ca Enterprise NVMe SSD U.2 ODP 3.84TB (J5102) 1e3b 00cb Enterprise NVMe SSD U.2 ODP 7.68TB (J5102) @@ -26609,12 +26677,16 @@ 1e3b 00dc Enterprise NVMe SSD U.2 ODP 30.72TB with SAMSUNG 32GB DRAM (J5001) 1e3b 00dd Enterprise NVMe SSD U.2 ODP 30.72TB with MT 32GB DRAM(J5001) 1e3b 00de Enterprise NVMe SSD U.2 ODP 15.36TB with SK 16GB DRAM(J5001D) - 1e3b 00df Enterprise NVMe SSD U.2 ODP 30.72TB with SAMSUNG 32GB DRAM(J5001D) + 1e3b 00df Enterprise NVMe SSD U.2 ODP 30.72TB with SAMSUNG 32GB DRAM(J5001) 1e3b 00e7 Enterprise NVMe SSD U.2 ODP 30.72TB with MT 32GB DRAM(J5001D) 1e3b 00e8 Enterprise NVMe SSD U.2 QDP 3.20TB (J5301) 1e3b 00e9 Enterprise NVMe SSD U.2 ODP 6.40TB (J5301) 1e3b 00ea Enterprise NVMe SSD U.2 QDP 3.20TB (J5301D) 1e3b 00eb Enterprise NVMe SSD U.2 ODP 6.40TB (J5301D) + 1e3b 00ec Enterprise NVMe SSD U.2 ODP 30.72TB with MT 32GB DRAM(J5101) + 1e3b 00ed Enterprise NVMe SSD U.2 ODP 30.72TB with MT 32GB DRAM(R5101) + 1e3b 00ee Enterprise NVMe SSD U.2 ODP 15.36B with SK 16GB DRAM(J5101) + 1e3b 00ef Enterprise NVMe SSD U.2 ODP 12.80TB with SK 16GB DRAM(J5301) 1e3b 00f0 Enterprise NVMe SSD U.2 0.40TB (X2900) 1e3b 00f1 Enterprise NVMe SSD U.2 0.80TB (X2900) 1e3b 00f2 Enterprise NVMe SSD U.2 1.60TB (X2900) @@ -26786,6 +26858,7 @@ 1001 Video Accelerator 1eb4 Quantum Nebula Microelectronics Technology Co.,Ltd. 3401 SSD Contoller +1eb6 Wuxi Stars Microsystem Technology Co., Ltd 1eb9 Senscomm Semiconductor, Inc 2020 SCM2625 Wi-Fi6 Network Adapter 1ebd EMERGETECH Company Ltd. @@ -26829,12 +26902,14 @@ 1eca Lightmatter 0000 Envise-B 1ed0 Hosin Global Electronics + 2283 Patriot P300 NVMe SSD (DRAM-less) 1ed2 FuriosaAI, Inc. 0000 Warboy 1111 RNGD 0000 1111 RNGD-S 0000 2222 RNGD VF 0000 3333 RNGD-S VF + 2222 RNGD-S 1ed3 Yeston 1ed5 Moore Threads Technology Co.,Ltd 0100 MTT S10 @@ -26918,6 +26993,7 @@ 1ef6 GrAI Matter Labs 1ef7 Shenzhen Gunnir Technology Development Co., Ltd 1efb Flexxon Pte Ltd +1eff Rebellions Inc. 1f02 Beijing Dayu Technology 1f03 Shenzhen Shichuangyi Electronics Co., Ltd 1202 MAP1202-Based NVMe SSD (DRAM-less) @@ -26947,7 +27023,27 @@ 1a01 M16104 Family Virtual Function 1f0f 0001 M16104 Family Virtual Function 2022 D1055AS PCI Express Switch Upstream Port + 3403 M18110 Family + 3404 M18110 Lx Family + 3405 M18110 Family BASE-T + 3406 M18110 Lx Family BASE-T + 3407 M18110 Family OCP + 3408 M18110 Lx Family OCP + 3409 M18110 Family BASE-T OCP + 340a M18110 Lx Family BASE-T OCP + 340b M18120 Family + 340c M18120 Lx Family + 340d M18120 Family BASE-T + 340e M18120 Lx Family BASE-T + 340f M18120 Family OCP + 3410 M18120 Lx Family OCP + 3411 M18120 Family BASE-T OCP + 3412 M18120 Lx Family BASE-T OCP + 3413 M18100 Family Virtual Function 9088 D1055AS PCI Express Switch Downstream Port +1f16 XConn Technologies +# XConn XC50256 CXL2.0/PCIe5.0 switch + c500 XC50256 1f17 Zettastone Technology 1f24 xFusion Digital Technologies Co., Ltd. 1058 EP500/EP600 NVMe SSD @@ -27148,6 +27244,25 @@ 1fe4 0077 Enterprise NVMe SSD U.2 6.40TB(HP630) 1fe4 0078 Enterprise NVMe SSD U.2 3.20TB(HP630) 1fe9 MemryX +# LinkData Technology (Tianjin) Co., LTD +1ff2 Linkdata + 10a1 NIC1160 Ethernet Controller Family + 1ff2 0c11 10GE Ethernet Adapter 1160-2X + 10a2 NIC1160 Ethernet Controller Virtual Function Family + 20a1 IOC2110 Storage Controller + 1ff2 0a11 2120-16i SATA3/SAS3 HBA Adapter + 1ff2 0a12 2120-8i SATA3/SAS3 HBA Adapter + 20a2 IOC2250 Storage Controller + 1ff2 0a21 2230-18i Tri-mode HBA Adapter + 1ff2 0a22 2230-10i Tri-mode HBA Adapter + 1ff2 0a23 2230-16i Tri-mode HBA Adapter + 1ff2 0a24 2230-8i Tri-mode HBA Adapter + 1ff2 0a28 2233-16i Tri-mode HBA Adapter + 30a2 ROC3250 Storage Controller + 1ff2 0b21 3260-18i Tri-mode RAID Adapter + 1ff2 0b22 3260-10i Tri-mode RAID Adapter + 1ff2 0b23 3260-16i Tri-mode RAID Adapter + 1ff2 0b24 3260-8i Tri-mode RAID Adapter 1ff4 DEEPX Co., Ltd. 0000 DX_M1 0001 DX_M1A @@ -27600,10 +27715,8 @@ 4c52 LR-LINK 1001 Smart Network Adapter 4c52 a008 LREG1008PT Single-port 1Gb Smart Ethernet Network Adapter - 4c52 a009 LREG1009PT Single-port 2.5Gb Smart Ethernet Network Adapter 1002 Smart Network Adapter 4c52 a006 LREG1006PT Single-port 1.2Gb Network Security Isolation Adapter - 4c52 a007 LREG1007PT Quad-port 10Gb Smart Ethernet Network Adapter 1003 Smart Network Adapter 1004 Smart Network Adapter 4c52 b010 LREG1010PF Single-port 10Gb FPGA Network Security Isolation Adapter @@ -27667,6 +27780,9 @@ 50b2 TerraTec Electronic GmbH 50ce System-on-Chip Engineering S.L. 0001 RELY-MIL-XMC-TSN-SWITCH + 0100 XMC_AV-Dual-ETH + 0101 XMC_AV-ETSN + 0102 XMC_AV-AFDX 5136 S S Technologies 5143 Qualcomm Inc 5145 Ensoniq (Old) @@ -29738,7 +29854,12 @@ 125d Ethernet Controller I226-IT 12d1 Ethernet Controller E830-CC for backplane 12d2 Ethernet Controller E830-CC for QSFP + 8086 0002 Ethernet Network Adapter E830-C-Q2 for OCP 3.0 + 8086 0004 Ethernet Network Adapter E830-CC-Q1 for OCP 3.0 12d3 Ethernet Controller E830-CC for SFP + 8086 0001 Ethernet Network Adapter E830-XXV-2 for OCP 3.0 + 8086 0003 Ethernet Network Adapter E830-XXV-2 + 8086 0004 Ethernet Network Adapter E830-XXV-4 for OCP 3.0 12d4 Ethernet Controller E830-CC for SFP-DD 12d5 Ethernet Controller E830-C for backplane 12d8 Ethernet Controller E830-C for QSFP @@ -30368,6 +30489,7 @@ 15fc Ethernet Connection (13) I219-V 15ff Ethernet Controller X710 for 10GBASE-T 1014 0000 PCIe3 4-port 10GbE Base-T Adapter + 108e 7b1f Quad Port 10GBase-T Adapter - CP 1137 0000 X710TLG GbE RJ45 PCIe NIC 1137 02c1 X710T2LG 2x10 GbE RJ45 PCIe NIC 1137 02c2 X710T4LG 4x10 GbE RJ45 PCIe NIC @@ -34334,6 +34456,7 @@ 37d9 X722 Hyper-V Virtual Function 3882 Ice Lake LPC Controller 38a4 Ice Lake SPI Controller + 38c8 Ice Lake-LP Smart Sound Technology Audio Controller 38e0 Ice Lake Management Engine Interface 3a00 82801JD/DO (ICH10 Family) 4-port SATA IDE Controller 3a02 82801JD/DO (ICH10 Family) SATA AHCI Controller @@ -34932,6 +35055,7 @@ 4641 12th Gen Core Processor Host Bridge/DRAM Registers 1028 0b10 Precision 3571 464d 12th Gen Core Processor PCI Express x4 Controller #0 + 464e Alder Lake-N Thunderbolt 4 USB Controller 464f 12th Gen Core Processor Gaussian & Neural Accelerator 1028 0b10 Precision 3571 4650 12th Gen Core Processor Host Bridge @@ -34978,8 +35102,13 @@ 4908 DG1 [Iris Xe Graphics] 4909 DG1 [Iris Xe MAX 100] 4940 4xxx Series QAT - 4942 4xxx Series QAT - 4944 4xxx Series QAT + 4941 4xxx Series QAT Virtual Function + 4942 401xx Series QAT + 4943 401xx Series QAT Virtual Function + 4944 402xx Series QAT + 4945 402xx Series QAT Virtual Function + 4946 420xx Series QAT + 4947 420xx Series QAT Virtual Function 4b00 Elkhart Lake eSPI Controller 4b23 Elkhart Lake SMBus Controller 4b24 Elkhart Lake SPI (Flash) Controller @@ -35107,6 +35236,7 @@ 51b0 Alder Lake PCI Express Root Port #9 51b1 Alder Lake PCI Express x1 Root Port #10 51bb Alder Lake-P PCH PCIe Root Port #4 + 51bd Alder Lake-P PCH PCIe Root Port #6 51bf Alder Lake PCH-P PCI Express Root Port #9 51c5 Alder Lake-P Serial IO I2C Controller #0 51c6 Alder Lake-P Serial IO I2C Controller #1 @@ -35166,7 +35296,15 @@ 8086 0001 EtherExpress PRO/100 Server Ethernet Adapter 530d 80310 (IOP) IO Processor 5481 Alder Lake-N PCH eSPI Controller + 54a3 Alder Lake-N SMBus + 54a4 Alder Lake-N SPI (flash) Controller + 54a8 Alder Lake-N Serial IO UART Host Controller + 54b0 Alder Lake-N PCI Express Root Port #9 + 54b1 Alder Lake-N PCI Express Root Port #10 + 54b2 Alder Lake-N PCI Express Root Port #11 + 54b3 Alder Lake-N PCI Express Root Port #12 54c8 Alder Lake-N PCH High Definition Audio Controller + 54d3 Alder Lake-N SATA AHCI Controller 54e0 Alder Lake-N PCH HECI Controller 54ed Alder Lake-N PCH USB 3.2 xHCI Host Controller 54ef Alder Lake-N PCH Shared SRAM @@ -35205,7 +35343,7 @@ 56bf DG2 [Arc Graphics A580E] 56c0 ATS-M [Data Center GPU Flex 170] 56c1 ATS-M [Data Center GPU Flex 140] - 56c2 ATS-M [Data Center GPU Flex 170G] + 56c2 ATS-M [Data Center GPU Flex 170V] 5780 Thunderbolt 80/120G Bridge [Barlow Ridge Host 80G 2023] 5781 Thunderbolt 80/120G NHI [Barlow Ridge Host 80G 2023] 5782 Thunderbolt 80/120G USB Controller [Barlow Ridge Host 80G 2023] @@ -35219,9 +35357,12 @@ 579e Ethernet Connection E825-C for SFP 57a4 Thunderbolt Bridge [Barlow Ridge Hub 40G 2023] 57a5 Thunderbolt USB Controller [Barlow Ridge Hub 40G 2023] + 57ae Ethernet Controller E610 Backplane + 57af Ethernet Controller E610 SFP 57b0 Ethernet Controller E610 10GBASE T 57b1 Ethernet Controller E610 2.5GBASE T 8086 0000 Ethernet Converged Network Adapter E610 + 57b2 Ethernet Controller E610 SGMII 5845 QEMU NVM Express Controller 1af4 1100 QEMU Virtual Machine 5900 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers @@ -35600,6 +35741,7 @@ 7a27 Raptor Lake-S PCH Shared SRAM 7a30 Raptor Lake PCI Express Root Port #9 7a38 Raptor Lake PCI Express Root Port #1 + 7a3a Raptor Point-S PCH - PCI Express Root Port 3 7a3b Raptor Lake PCI Express Root Port #4 7a40 Raptor Lake PCI Express Root Port #17 7a44 Raptor Lake PCI Express Root Port #21 @@ -35646,7 +35788,10 @@ 8086 0094 Wi-Fi 6 AX201 160MHz 7afc Alder Lake-S PCH Serial IO I2C Controller #4 7afd Alder Lake-S PCH Serial IO I2C Controller #5 + 7d03 Meteor Lake-P Dynamic Tuning Technology 7d0b Volume Management Device NVMe RAID Controller Intel Corporation + 7d0d Meteor Lake-P Platform Monitoring Technology + 7d19 Meteor Lake IPU 7d1d Meteor Lake NPU 7d40 Meteor Lake-M [Intel Graphics] 7d41 Arrow Lake-U [Intel Graphics] @@ -35668,10 +35813,15 @@ 7e30 Meteor Lake-P Serial IO SPI Controller #1 7e40 Meteor Lake PCH CNVi WiFi 8086 0094 Wi-Fi 6E AX211 160MHz +# Refer from Intel Meteor Lake EDS (doc#640228) under its "Device IDs" section. + 7e45 Meteor Lake-P Integrated Sensor Hub 7e46 Meteor Lake-P Serial IO SPI Controller #2 + 7e4c Meteor Lake-P Gaussian & Neural-Network Accelerator 7e50 Meteor Lake-P Serial IO I2C Controller #4 7e51 Meteor Lake-P Serial IO I2C Controller #5 7e52 Meteor Lake-P Serial IO UART Controller #2 + 7e70 Meteor Lake-P CSME HECI #1 + 7e73 Meteor Lake-P Keyboard and Text (KT) Redirection 7e78 Meteor Lake-P Serial IO I2C Controller #0 7e79 Meteor Lake-P Serial IO I2C Controller #1 7e7a Meteor Lake-P Serial IO I2C Controller #2 @@ -36758,6 +36908,7 @@ a72f Raptor Lake-P Thunderbolt 4 PCI Express Root Port #2 a73e Raptor Lake-P Thunderbolt 4 NHI #0 1028 0c06 Precision 3580 + a740 Raptor Lake-S 8+12 - Host Bridge/DRAM Controller a74d Raptor Lake PCIe 4.0 Graphics Port a74f GNA Scoring Accelerator module 1028 0c06 Precision 3580 @@ -36851,6 +37002,11 @@ d156 Core Processor Semaphore and Scratchpad Registers d157 Core Processor System Control and Status Registers d158 Core Processor Miscellaneous Registers + e202 Battlemage G21 [Intel Graphics] + e20b Battlemage G21 [Intel Graphics] + e20c Battlemage G21 [Intel Graphics] + e20d Battlemage G21 [Intel Graphics] + e212 Battlemage G21 [Intel Graphics] f1a5 SSD 600P Series 8086 390a SSDPEKKW256G7 256GB f1a6 SSD DC P4101/Pro 7600p/760p/E 6100p Series @@ -36921,7 +37077,7 @@ 0119 WX1860-LC Gigabit Ethernet Controller Virtual Function 011a WX1860A1 Gigabit Ethernet Controller Virtual Function 011b WX1860AL1 Gigabit Ethernet Controller Virtual Function - 1000 Ethernet Controller RP1000 Virtual Function for 10GbE SFP+ + 1000 Ethernet Controller SP1000A Virtual Function for 10GbE SFP+ 1001 Ethernet Controller SP1000A for 10GbE SFP+ 1bd4 0084 Ethernet Controller SP1000A for 10GbE SFP+(lldp) 1bd4 0085 Ethernet Controller SP1000A for 10GBASE-T @@ -36931,7 +37087,7 @@ 8088 0000 Ethernet Network Adaptor RP1000 for 10GbE SFP+ 8088 0300 Ethernet Network Adaptor RP1000-A03 for 10GbE SFP+ 8088 0400 Ethernet Network Adaptor RP1000-A04 for 10GbE SFP+ - 2000 Ethernet Controller RP2000 Virtual Function for 10GbE SFP+ + 2000 Ethernet Controller WX1820AL Virtual Function for 10GbE SFP+ 2001 Ethernet Controller WX1820AL for 10GbE SFP+ 8088 2000 Ethernet Network Adaptor RP2000 for 10GbE SFP+ 8088 2300 Ethernet Network Adaptor RP2000-A03 for 10GbE SFP+ @@ -36943,7 +37099,17 @@ 8384 SigmaTel 8401 TRENDware International Inc. 8510 Sietium Semiconductor Co., Ltd. - 0201 GenBu02 [GB2062-PCIe-C0] + 0201 GenBu02 Series GPU + 8510 0001 GB2062-PUB-LPDDR + 8510 0002 GB2062-PCIe-C0 + 8510 0003 GB2062-PCIe-C41 + 8510 0004 GB2062-PCIe-HIEILP4 + 8510 0005 CQ2040-PCIe-C21 + 8510 0007 GB2062-PCIe-C40 + 8510 0008 CQ2040-MXM-M60 + 8510 0009 GB2062-PCIe-C20 + 8510 000c CQ2040-PUB + 8510 0201 GB2062-PUB-DDR # nee ScaleMP 8686 SAP 1010 vSMP Foundation controller [vSMP CTL] @@ -37316,6 +37482,9 @@ 103c 1101 Smart Array P416ie-m SR G10 105b 1211 HBA 8238-16i 105b 1321 HBA 8242-24i + 1137 02f8 24G TriMode M1 RAID 4GB FBWC 32D + 1137 02f9 24G TriMode M1 RAID 4GB FBWC 16D + 1137 02fa 24G TriMode M1 HBA 16D 13fe 8312 SKY-9200 MIC-8312BridgeB 152d 8a22 QS-8204-8i 152d 8a23 QS-8238-16i diff --git a/pkg/flist/flist.go b/pkg/flist/flist.go index 844d03e89..f99b10ece 100644 --- a/pkg/flist/flist.go +++ b/pkg/flist/flist.go @@ -6,7 +6,9 @@ import ( "crypto/md5" "fmt" "io" + "net" "net/http" + "net/url" "os" "os/exec" "path" @@ -78,6 +80,7 @@ type defaultSystem struct{} func (d *defaultSystem) Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { return syscall.Mount(source, target, fstype, flags, data) } + func (d *defaultSystem) Unmount(target string, flags int) error { return syscall.Unmount(target, flags) } @@ -190,13 +193,13 @@ func New(root string, storage *stubs.StorageModuleStub) pkg.Flister { // MountRO mounts an flist in read-only mode. This mount then can be shared between multiple rw mounts // TODO: how to know that this ro mount is no longer used, hence can be unmounted and cleaned up? -func (f *flistModule) mountRO(url, storage string) (string, error) { +func (f *flistModule) mountRO(url, storage, nsName string) (string, error) { // this should return always the flist mountpoint. which is used // as a base for all RW mounts. sublog := log.With().Str("url", url).Str("storage", storage).Logger() sublog.Info().Msg("request to mount flist") - hash, flistPath, err := f.downloadFlist(url) + hash, flistPath, err := f.downloadFlist(url, nsName) if err != nil { sublog.Err(err).Msg("fail to download flist") return "", err @@ -255,11 +258,6 @@ func (f *flistModule) mountRO(url, storage string) (string, error) { } args = append(args, mountpoint) - // we run the flist binary - nsName := defaultNamespace - if namespace.Exists(publicNamespace) { - nsName = publicNamespace - } // we do get the namespace via the commander // only to be able to mock it via tests. @@ -391,7 +389,6 @@ func (f *flistModule) mountOverlay(ctx context.Context, name, ro string, opt *pk ro, rw, wd, ), ) - if err != nil { return errors.Wrap(err, "failed to mount overlay") } @@ -416,6 +413,10 @@ func (f *flistModule) Exists(name string) (bool, error) { } func (f *flistModule) Mount(name, url string, opt pkg.MountOptions) (string, error) { + return f.mountInNamespace(name, url, opt, defaultNamespace) +} + +func (f *flistModule) mountInNamespace(name, url string, opt pkg.MountOptions, namespace string) (string, error) { sublog := log.With().Str("name", name).Str("url", url).Str("storage", opt.Storage).Logger() sublog.Info().Msgf("request to mount flist: %+v", opt) @@ -436,7 +437,7 @@ func (f *flistModule) Mount(name, url string, opt pkg.MountOptions) (string, err return "", errors.Wrap(err, "validating of mount point failed") } - ro, err := f.mountRO(url, opt.Storage) + ro, err := f.mountRO(url, opt.Storage, namespace) if err != nil { return "", errors.Wrap(err, "ro mount of flist failed") } @@ -522,6 +523,7 @@ func (f *flistModule) waitMountpoint(path string, seconds int) error { return fmt.Errorf("was not mounted in time") } + func (f *flistModule) isMountpoint(path string) error { log.Debug().Str("mnt", path).Msg("testing mountpoint") return f.commander.Command("mountpoint", path).Run() @@ -612,12 +614,15 @@ func (f *flistModule) FlistHash(url string) (string, error) { // first check if the md5 of the flist is available md5URL := url + ".md5" - resp, err := f.httpClient.Get(md5URL) + resp, con, err := f.downloadInNamespace(defaultNamespace, md5URL) if err != nil { return "", errors.Wrapf(err, "failed to get flist hash from '%s'", md5URL) } - defer resp.Body.Close() + defer func() { + resp.Body.Close() + con.Close() + }() if resp.StatusCode == http.StatusNotFound { return "", ErrHashNotSupported @@ -638,7 +643,7 @@ func (f *flistModule) FlistHash(url string) (string, error) { return hashStr, nil } -func (f *flistModule) downloadFlist(url string) (Hash, Path, error) { +func (f *flistModule) downloadFlist(url, namespace string) (Hash, Path, error) { // the problem here is that the same url (to an flist) might // be completely differnet flists. because the flist was update // on remote. so we can't optimize the download by avoiding redownloading @@ -651,11 +656,18 @@ func (f *flistModule) downloadFlist(url string) (Hash, Path, error) { // for now we re-download every time and compute the hash on the fly // we don't have the flist locally yet, let's download it - resp, err := f.httpClient.Get(url) + + resp, con, err := f.downloadInNamespace(namespace, url) if err != nil { return "", "", err } - defer resp.Body.Close() + + defer func() { + resp.Body.Close() + if con != nil { + con.Close() + } + }() if resp.StatusCode != 200 { return "", "", fmt.Errorf("fail to download flist: %v", resp.Status) @@ -696,3 +708,60 @@ func (f *flistModule) saveFlist(r io.Reader) (Hash, Path, error) { } var _ pkg.Flister = (*flistModule)(nil) + +func (f *flistModule) downloadInNamespace(name, u string) (resp *http.Response, con net.Conn, err error) { + if len(name) == 0 { + resp, err = f.httpClient.Get(u) + return + } + + namespace, err := namespace.GetByName(name) + if err != nil { + return resp, con, errors.Wrapf(err, "failed to get namespace %s", name) + } + + err = namespace.Do(func(_ ns.NetNS) error { + hostPort, err := parseURL(u) + if err != nil { + return err + } + + con, err = net.Dial("tcp", hostPort) + if err != nil { + return errors.Wrap(err, "failed to start tcp connection") + } + + cl := http.Client{ + Transport: &http.Transport{ + DisableKeepAlives: true, + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + return con, nil + }, + }, + } + + resp, err = cl.Get(u) + return err + }) + + return +} + +func parseURL(u string) (hostPort string, err error) { + rawURL, err := url.Parse(u) + if err != nil { + return "", errors.Wrap(err, "failed to parse url") + } + + port := rawURL.Port() + if port == "" { + p, err := net.LookupPort("tcp", rawURL.Scheme) + if err != nil { + return "", errors.Wrap(err, "failed to lookup url port") + } + port = fmt.Sprint(p) + } + + hostPort = net.JoinHostPort(rawURL.Hostname(), port) + return hostPort, nil +} diff --git a/pkg/flist/flist_test.go b/pkg/flist/flist_test.go index 179a6b947..d52688f26 100644 --- a/pkg/flist/flist_test.go +++ b/pkg/flist/flist_test.go @@ -18,11 +18,9 @@ import ( "github.com/threefoldtech/zos/pkg/gridtypes" ) -var ( - templ = template.Must(template.New("script").Parse(` +var templ = template.Must(template.New("script").Parse(` echo "mount ready" > {{.log}} `)) -) // StorageMock is a mock object of the storage modules type StorageMock struct { @@ -73,8 +71,8 @@ func (t *testCommander) args(args ...string) (map[string]string, []string) { continue } - //if no -, then it must be a value. - //so if lk is set, update, otherwise append to r + // if no -, then it must be a value. + // so if lk is set, update, otherwise append to r if len(lk) > 0 { v[lk] = arg lk = "" @@ -161,7 +159,7 @@ func TestMountUnmount(t *testing.T) { sys.On("Mount", "overlay", filepath.Join(root, "mountpoint", name), "overlay", uintptr(syscall.MS_NOATIME), mock.Anything).Return(nil) - mnt, err := flister.Mount(name, "https://hub.grid.tf/thabet/redis.flist", pkg.DefaultMountOptions) + mnt, err := flister.mountInNamespace(name, "https://hub.grid.tf/thabet/redis.flist", pkg.DefaultMountOptions, "") require.NoError(t, err) // Trick flister into thinking that 0-fs has exited @@ -188,7 +186,7 @@ func TestMountUnmountRO(t *testing.T) { flist := mock.Anything sys.On("Mount", flist, filepath.Join(root, "mountpoint", name), "bind", uintptr(syscall.MS_BIND), "").Return(nil) - mnt, err := flister.Mount(name, "https://hub.grid.tf/thabet/redis.flist", pkg.ReadOnlyMountOptions) + mnt, err := flister.mountInNamespace(name, "https://hub.grid.tf/thabet/redis.flist", pkg.ReadOnlyMountOptions, "") require.NoError(t, err) // Trick flister into thinking that 0-fs has exited @@ -225,17 +223,16 @@ func TestIsolation(t *testing.T) { name2 := "test2" sys.On("Mount", "overlay", filepath.Join(root, "mountpoint", name2), "overlay", uintptr(syscall.MS_NOATIME), mock.Anything).Return(nil) - path1, err := flister.Mount(name1, "https://hub.grid.tf/thabet/redis.flist", pkg.DefaultMountOptions) + path1, err := flister.mountInNamespace(name1, "https://hub.grid.tf/thabet/redis.flist", pkg.DefaultMountOptions, "") require.NoError(err) args1 := cmder.m - path2, err := flister.Mount(name2, "https://hub.grid.tf/thabet/redis.flist", pkg.DefaultMountOptions) + path2, err := flister.mountInNamespace(name2, "https://hub.grid.tf/thabet/redis.flist", pkg.DefaultMountOptions, "") require.NoError(err) args2 := cmder.m require.NotEqual(path1, path2) require.Equal(args1, args2) - } func TestDownloadFlist(t *testing.T) { @@ -249,14 +246,14 @@ func TestDownloadFlist(t *testing.T) { f := newFlister(root, strg, cmder, sys) - hash1, path1, err := f.downloadFlist("https://hub.grid.tf/thabet/redis.flist") + hash1, path1, err := f.downloadFlist("https://hub.grid.tf/thabet/redis.flist", "") require.NoError(err) // now corrupt the flist err = os.Truncate(string(path1), 512) require.NoError(err) - hash2, path2, err := f.downloadFlist("https://hub.grid.tf/thabet/redis.flist") + hash2, path2, err := f.downloadFlist("https://hub.grid.tf/thabet/redis.flist", "") require.NoError(err) require.EqualValues(path1, path2) diff --git a/pkg/network.go b/pkg/network.go index 25bf53d31..f373cd215 100644 --- a/pkg/network.go +++ b/pkg/network.go @@ -85,12 +85,12 @@ type Networker interface { // // Leave delete a container nameapce created by Join // Leave(networkdID NetID, containerID string) (err error) - // ZDBPrepare creates a network namespace with a macvlan interface into it - // to allow the 0-db container to be publicly accessible - // it retusn the name of the network namespace created + // EnsureZDBPrepare ensures a network namespace is created with a macvlan + // interface into it to allow the 0-db container to be publicly accessible + // it returns the name of the network namespace created // id is the zdb id (should be unique) is used to drive the hw mac // address for the interface so they always get the same IP - ZDBPrepare(id string) (string, error) + EnsureZDBPrepare(id string) (string, error) // ZDBDestroy is the opposite of ZDPrepare, it makes sure network setup done // for zdb is rewind. ns param is the namespace return by the ZDBPrepare @@ -231,9 +231,9 @@ type NetID = zos.NetID type IfaceType string const ( - //VlanIface means we use vlan for the public interface + // VlanIface means we use vlan for the public interface VlanIface IfaceType = "vlan" - //MacVlanIface means we use macvlan for the public interface + // MacVlanIface means we use macvlan for the public interface MacVlanIface IfaceType = "macvlan" ) diff --git a/pkg/network/mycelium/config.go b/pkg/network/mycelium/config.go new file mode 100644 index 000000000..e80898539 --- /dev/null +++ b/pkg/network/mycelium/config.go @@ -0,0 +1,47 @@ +package mycelium + +import ( + "context" + "crypto/ed25519" + + "github.com/oasisprotocol/curve25519-voi/primitives/x25519" + "github.com/pkg/errors" +) + +type NodeConfig struct { + KeyFile string + TunName string + Peers []string + privateKey x25519.PrivateKey +} + +func (n *NodeConfig) FindPeers(ctx context.Context, filter ...Filter) error { + // fetching a peer list goes as this + // - Always include the list of peers from + peers, err := fetchZosMyList() + if err != nil { + return errors.Wrap(err, "failed to get zos public peer list") + } + + peers, err = peers.Ups(filter...) + if err != nil { + return errors.Wrap(err, "failed to filter out peer list") + } + + n.Peers = peers + return nil +} + +// GenerateConfig creates a new mycelium configuration +func GenerateConfig(privateKey ed25519.PrivateKey) (cfg NodeConfig) { + cfg = NodeConfig{ + KeyFile: confPath, + TunName: tunName, + } + + if privateKey != nil { + cfg.privateKey = x25519.PrivateKey(x25519.EdPrivateKeyToX25519([]byte(privateKey))) + } + + return +} diff --git a/pkg/network/mycelium/mycelium.go b/pkg/network/mycelium/mycelium.go new file mode 100644 index 000000000..482922029 --- /dev/null +++ b/pkg/network/mycelium/mycelium.go @@ -0,0 +1,268 @@ +package mycelium + +import ( + "context" + "crypto/ed25519" + "crypto/sha512" + "encoding/json" + "fmt" + "net" + "os" + "os/exec" + "path/filepath" + "strings" + "time" + + "github.com/oasisprotocol/curve25519-voi/primitives/x25519" + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "github.com/threefoldtech/zos/pkg/network/namespace" + "github.com/threefoldtech/zos/pkg/zinit" +) + +const ( + tunName = "my0" + myceliumBin = "mycelium" + zinitService = "mycelium" + confPath = "/tmp/mycelium_priv_key.bin" + MyListenTCP = 9651 +) + +// MyceliumServer represent a mycelium server +type MyceliumServer struct { + cfg *NodeConfig + ns string +} + +type MyceliumInspection struct { + PublicKey string `json:"publicKey"` + Address net.IP `json:"address"` +} + +// NewMyceliumServer create a new mycelium Server +func NewMyceliumServer(cfg *NodeConfig) *MyceliumServer { + return &MyceliumServer{ + cfg: cfg, + } +} + +func (s *MyceliumServer) Restart(z *zinit.Client) error { + return z.Kill(zinitService, zinit.SIGTERM) +} + +func (s *MyceliumServer) Reload(z *zinit.Client) error { + return z.Kill(zinitService, zinit.SIGHUP) +} + +// Start creates a mycelium zinit service and starts it +func (s *MyceliumServer) Ensure(z *zinit.Client, ns string) error { + if !namespace.Exists(ns) { + return fmt.Errorf("invalid namespace '%s'", ns) + } + s.ns = ns + + if err := writeKey(confPath, s.cfg.privateKey); err != nil { + return err + } + + // service found. + // better if we just stop, forget and start over to make + // sure we using the right exec params + if _, err := z.Status(zinitService); err == nil { + // not here we need to stop it + if err := z.StopWait(5*time.Second, zinitService); err != nil && !errors.Is(err, zinit.ErrUnknownService) { + return errors.Wrap(err, "failed to stop mycelium service") + } + if err := z.Forget(zinitService); err != nil && !errors.Is(err, zinit.ErrUnknownService) { + return errors.Wrap(err, "failed to forget mycelium service") + } + } + + bin, err := exec.LookPath(myceliumBin) + if err != nil { + return err + } + + args := []string{ + "ip", "netns", "exec", ns, + bin, + "--key-file", confPath, + "--tun-name", s.cfg.TunName, + "--peers", + } + + args = append(args, s.cfg.Peers...) + + err = zinit.AddService(zinitService, zinit.InitService{ + Exec: strings.Join(args, " "), + After: []string{ + "node-ready", + }, + }) + if err != nil { + return err + } + + if err := z.Monitor(zinitService); err != nil && !errors.Is(err, zinit.ErrAlreadyMonitored) { + return err + } + + return z.StartWait(time.Second*20, zinitService) +} + +func EnsureMycelium(ctx context.Context, privateKey ed25519.PrivateKey, ns MyceliumNamespace) (*MyceliumServer, error) { + // Filter out all the nodes from the same + // segment so we do not just connect locally + ips, err := ns.GetIPs() // returns ipv6 only + if err != nil { + return nil, errors.Wrap(err, "failed to get ndmz public ipv6") + } + + var ranges Ranges + for _, ip := range ips { + if ip.IP.IsGlobalUnicast() { + ranges = append(ranges, ip) + } + } + + log.Info().Msgf("filtering out peers from ranges: %s", ranges) + filter := Exclude(ranges) + z := zinit.Default() + + cfg := GenerateConfig(privateKey) + if err := cfg.FindPeers(ctx, filter); err != nil { + return nil, err + } + + server := NewMyceliumServer(&cfg) + if err := server.Ensure(z, ns.Name()); err != nil { + return nil, err + } + + myInspec, err := server.InspectMycelium() + if err != nil { + return nil, err + } + + gw, err := myInspec.Gateway() + if err != nil { + return nil, errors.Wrap(err, "fail read mycelium subnet") + } + + if err := ns.SetMyIP(gw, nil); err != nil { + return nil, errors.Wrap(err, "fail to configure mycelium subnet gateway IP") + } + + return server, nil +} + +func (s *MyceliumServer) InspectMycelium() (inspection MyceliumInspection, err error) { + // we check if the file exists before we do inspect because mycelium will create a random seed + // file if file does not exist + _, err = os.Stat(confPath) + if err != nil { + return inspection, err + } + + bin, err := exec.LookPath(myceliumBin) + if err != nil { + return inspection, err + } + + output, err := exec.Command("ip", "netns", "exec", s.ns, bin, "inspect", "--json", "--key-file", confPath).Output() + if err != nil { + return inspection, errors.Wrap(err, "failed to inspect mycelium ip") + } + + if err := json.Unmarshal(output, &inspection); err != nil { + return inspection, errors.Wrap(err, "failed to load mycelium information from key") + } + + return +} + +// IP return the address in the 400::/7 subnet allocated by mycelium +func (m *MyceliumInspection) IP() net.IP { + return net.IP(m.Address) +} + +// Subnet return the 400::/64 subnet allocated by mycelium +func (m *MyceliumInspection) Subnet() (subnet net.IPNet, err error) { + ipv6 := m.Address.To16() + if ipv6 == nil { + return subnet, errors.Errorf("invalid mycelium ip") + } + + ip := make(net.IP, net.IPv6len) + copy(ip[0:8], ipv6[0:8]) + + subnet = net.IPNet{ + IP: ip, + Mask: net.CIDRMask(64, 128), + } + + return +} + +// Gateway derive the gateway IP from the mycelium IP in the /64 range. +func (m *MyceliumInspection) Gateway() (gw net.IPNet, err error) { + subnet, err := m.Subnet() + if err != nil { + return gw, err + } + + ip := subnet.IP + ip[net.IPv6len-1] = 1 + + gw = net.IPNet{ + IP: ip, + Mask: net.CIDRMask(64, 128), + } + + return +} + +// Tun return the name of the TUN interface created by mycelium +func (s *MyceliumServer) Tun() string { + return s.cfg.TunName +} + +// IPFor return an IP address out of the node allocated subnet by hasing b and using it +// to generate the last 64 bits of the IPV6 address +func (m *MyceliumInspection) IPFor(b []byte) (net.IPNet, error) { + subnet, err := m.Subnet() + if err != nil { + return net.IPNet{}, err + } + + ip := make([]byte, net.IPv6len) + copy(ip, subnet.IP) + + subIP, err := subnetFor(ip, b) + if err != nil { + return net.IPNet{}, err + } + + return net.IPNet{ + IP: subIP, + Mask: net.CIDRMask(64, 128), + }, nil +} + +func subnetFor(prefix net.IP, b []byte) (net.IP, error) { + h := sha512.New() + if _, err := h.Write(b); err != nil { + return nil, err + } + digest := h.Sum(nil) + copy(prefix[8:], digest[:8]) + return prefix, nil +} + +func writeKey(path string, privateKey x25519.PrivateKey) error { + if err := os.MkdirAll(filepath.Dir(path), 0770); err != nil { + return err + } + + return os.WriteFile(path, privateKey[:], 0666) +} diff --git a/pkg/network/mycelium/namespace.go b/pkg/network/mycelium/namespace.go new file mode 100644 index 000000000..a722c914d --- /dev/null +++ b/pkg/network/mycelium/namespace.go @@ -0,0 +1,269 @@ +package mycelium + +import ( + "fmt" + "net" + "os" + + "github.com/containernetworking/plugins/pkg/ns" + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "github.com/threefoldtech/zos/pkg/network/bridge" + "github.com/threefoldtech/zos/pkg/network/ifaceutil" + "github.com/threefoldtech/zos/pkg/network/macvlan" + "github.com/threefoldtech/zos/pkg/network/namespace" + "github.com/threefoldtech/zos/pkg/network/types" + "github.com/vishvananda/netlink" +) + +const ( + // MyceliumNSInf inside the namespace + MyceliumNSInf = "nmy6" + myceliumBridge = types.MyceliumBridge +) + +var MyRange = net.IPNet{ + IP: net.ParseIP("400::"), + Mask: net.CIDRMask(7, 128), +} + +type MyceliumNamespace interface { + Name() string + // IsIPv4Only checks if namespace has NO public ipv6 on any of its interfaces + IsIPv4Only() (bool, error) + // GetIPs return a list of all IPv6 inside this namespace. + GetIPs() ([]net.IPNet, error) + // SetMyIP sets the mycelium ipv6 on the nmy6 iterface. + SetMyIP(ip net.IPNet, gw net.IP) error +} + +// ensureMy Plumbing this ensures that the mycelium plumbing is in place inside this namespace +func ensureMyPlumbing(netNS ns.NetNS) error { + if !bridge.Exists(myceliumBridge) { + if _, err := bridge.New(myceliumBridge); err != nil { + return errors.Wrapf(err, "couldn't create bridge %s", myceliumBridge) + } + } + + if err := dumdumHack(); err != nil { + log.Error().Err(err).Msg("failed to create the dummy hack for mycelium-bridge") + } + + if !ifaceutil.Exists(MyceliumNSInf, netNS) { + if _, err := macvlan.Create(MyceliumNSInf, myceliumBridge, netNS); err != nil { + return errors.Wrapf(err, "couldn't create %s inside", MyceliumNSInf) + } + } + + return netNS.Do(func(_ ns.NetNS) error { + link, err := netlink.LinkByName(MyceliumNSInf) + if err != nil { + return err + } + + return netlink.LinkSetUp(link) + }) +} + +func dumdumHack() error { + // dumdum hack. this hack to fix a weird issue with linux kernel + // 5.10.version 55 + // it seems that the macvlan on a bridge does not bring the bridge + // up. So we have to plug in a dummy device into myceliumBridge and set + // the device up to keep the bridge state UP. + br, err := bridge.Get(myceliumBridge) + if err != nil { + return errors.Wrap(err, "failed to get br-my") + } + + const name = "mydumdum" + link, err := netlink.LinkByName(name) + if _, ok := err.(netlink.LinkNotFoundError); ok { + if err := netlink.LinkAdd(&netlink.Dummy{ + LinkAttrs: netlink.LinkAttrs{ + NetNsID: -1, + TxQLen: -1, + Name: name, + }, + }); err != nil { + return err + } + + link, err = netlink.LinkByName(name) + if err != nil { + return errors.Wrap(err, "failed to get mydumdum device") + } + } else if err != nil { + return err + } + + if err := netlink.LinkSetMaster(link, br); err != nil { + return err + } + + return netlink.LinkSetUp(link) +} + +func NewMyNamespace(ns string) (MyceliumNamespace, error) { + myNs, err := namespace.GetByName(ns) + if err != nil { + return nil, errors.Wrapf(err, "namespace '%s' not found", ns) + } + if err := ensureMyPlumbing(myNs); err != nil { + return nil, errors.Wrapf(err, "failed to prepare namespace '%s' for mycelium", ns) + } + + return &myNS{ns}, nil +} + +type myNS struct { + ns string +} + +func (d *myNS) Name() string { + return d.ns +} + +func (d *myNS) setGw(gw net.IP) error { + ipv6routes, err := netlink.RouteList(nil, netlink.FAMILY_V6) + if err != nil { + return err + } + + for _, route := range ipv6routes { + if route.Dst == nil { + // default route! + continue + } + if route.Dst.String() == MyRange.String() { + // we found a match + if err := netlink.RouteDel(&route); err != nil { + return err + } + } + } + + // now add route + return netlink.RouteAdd(&netlink.Route{ + Dst: &MyRange, + Gw: gw, + }) +} + +func (d *myNS) SetMyIP(subnet net.IPNet, gw net.IP) error { + netns, err := namespace.GetByName(d.ns) + if err != nil { + return err + } + defer netns.Close() + + if ip6 := subnet.IP.To16(); ip6 == nil { + return fmt.Errorf("expecting ipv6 for mycelium interface") + } + + err = netns.Do(func(_ ns.NetNS) error { + link, err := netlink.LinkByName(MyceliumNSInf) + if err != nil { + return err + } + + ips, err := netlink.AddrList(link, netlink.FAMILY_V6) + if err != nil { + return err + } + + for _, ip := range ips { + if MyRange.Contains(ip.IP) { + _ = netlink.AddrDel(link, &ip) + } + } + + if err := netlink.AddrAdd(link, &netlink.Addr{ + IPNet: &subnet, + }); err != nil && !os.IsExist(err) { + return err + } + + if gw == nil { + return nil + } + // set gw for entire mycelium range + + return d.setGw(gw) + }) + return err +} + +func (n *myNS) GetIPs() ([]net.IPNet, error) { + netns, err := namespace.GetByName(n.ns) + if err != nil { + return nil, err + } + + defer netns.Close() + + var results []net.IPNet + err = netns.Do(func(_ ns.NetNS) error { + links, err := netlink.LinkList() + if err != nil { + return errors.Wrap(err, "failed to list interfaces") + } + + for _, link := range links { + ips, err := netlink.AddrList(link, netlink.FAMILY_V6) + if err != nil { + return err + } + + for _, ip := range ips { + results = append(results, *ip.IPNet) + } + } + + return nil + }) + + return results, err +} + +func (n *myNS) IsIPv4Only() (bool, error) { + // this is true if DMZPub6 only has local not routable ipv6 addresses + // DMZPub6 + netNS, err := namespace.GetByName(n.ns) + if err != nil { + return false, errors.Wrap(err, "failed to get ndmz namespace") + } + defer netNS.Close() + + var ipv4Only bool + err = netNS.Do(func(_ ns.NetNS) error { + links, err := netlink.LinkList() + if err != nil { + return errors.Wrap(err, "failed to list interfaces") + } + + for _, link := range links { + ips, err := netlink.AddrList(link, netlink.FAMILY_V6) + if err != nil { + return errors.Wrapf(err, "failed to list '%s' ips", link.Attrs().Name) + } + + for _, ip := range ips { + if MyRange.Contains(ip.IP) { + continue + } + + if ip.IP.IsGlobalUnicast() && !ip.IP.IsPrivate() { + // we found a public IPv6 so we are not ipv4 so mycelium can peer + // with other ipv6 peers + return nil + } + } + } + + ipv4Only = true + return nil + }) + + return ipv4Only, err +} diff --git a/pkg/network/mycelium/public_peerlist.go b/pkg/network/mycelium/public_peerlist.go new file mode 100644 index 000000000..30a6cc171 --- /dev/null +++ b/pkg/network/mycelium/public_peerlist.go @@ -0,0 +1,90 @@ +package mycelium + +import ( + "net" + "net/url" + + "github.com/rs/zerolog/log" + "github.com/threefoldtech/zos/pkg/environment" +) + +// Peers is a peers list +type Peers []string + +type Filter func(ip net.IP) bool + +// Ranges is a list of net.IPNet +type Ranges []net.IPNet + +// Exclude ranges, return IPs that are NOT in the given ranges +func Exclude(ranges Ranges) Filter { + return func(ip net.IP) bool { + for _, n := range ranges { + if n.Contains(ip) { + return false + } + } + return true + } +} + +// Include ranges, return IPs that are IN one of the given ranges +func Include(ranges Ranges) Filter { + return func(ip net.IP) bool { + for _, n := range ranges { + if n.Contains(ip) { + return true + } + } + return false + } +} + +// IPV4Only is an IPFilter function that filters out non IPv4 address +func IPV4Only(ip net.IP) bool { + return ip.To4() != nil +} + +func fetchZosMyList() (Peers, error) { + cfg, err := environment.GetConfig() + if err != nil { + return nil, err + } + + return cfg.Mycelium.Peers, nil +} + +// Ups return all the peers that are marked up from the PeerList p +func (p Peers) Ups(filter ...Filter) (Peers, error) { + var peers Peers +next: + for _, n := range p { + if len(filter) == 0 { + peers = append(peers, n) + continue + } + // we have filters, we need to process the endpoint + u, err := url.Parse(n) + if err != nil { + log.Error().Err(err).Str("url", n).Msg("failed to parse url") + continue + } + ips, err := net.LookupIP(u.Hostname()) + if err != nil { + log.Error().Err(err).Str("url", n).Msg("failed to lookup ip") + continue + } + + for _, ip := range ips { + for _, f := range filter { + if !f(ip) { + continue next + } + } + } + + peers = append(peers, n) + } + + return peers, nil +} diff --git a/pkg/network/networker.go b/pkg/network/networker.go index f85cbb615..ccef4a6d0 100644 --- a/pkg/network/networker.go +++ b/pkg/network/networker.go @@ -24,6 +24,7 @@ import ( "github.com/threefoldtech/zos/pkg/gridtypes/zos" "github.com/threefoldtech/zos/pkg/network/bootstrap" "github.com/threefoldtech/zos/pkg/network/iperf" + "github.com/threefoldtech/zos/pkg/network/mycelium" "github.com/threefoldtech/zos/pkg/network/ndmz" "github.com/threefoldtech/zos/pkg/network/public" "github.com/threefoldtech/zos/pkg/network/tuntap" @@ -56,7 +57,8 @@ const ( // PubIface is pub interface name of the interface used in the 0-db network namespace PubIface = "eth0" // ZDBYggIface is ygg interface name of the interface used in the 0-db network namespace - ZDBYggIface = "ygg0" + ZDBYggIface = "ygg0" + ZDBMyceliumIface = "my0" networkDir = "networks" linkDir = "link" @@ -81,14 +83,15 @@ type networker struct { myceliumKeyDir string portSet *set.UIntSet - ndmz ndmz.DMZ - ygg *yggdrasil.YggServer + ndmz ndmz.DMZ + ygg *yggdrasil.YggServer + mycelium *mycelium.MyceliumServer } var _ pkg.Networker = (*networker)(nil) // NewNetworker create a new pkg.Networker that can be used over zbus -func NewNetworker(identity *stubs.IdentityManagerStub, ndmz ndmz.DMZ, ygg *yggdrasil.YggServer) (pkg.Networker, error) { +func NewNetworker(identity *stubs.IdentityManagerStub, ndmz ndmz.DMZ, ygg *yggdrasil.YggServer, myc *mycelium.MyceliumServer) (pkg.Networker, error) { vd, err := cache.VolatileDir("networkd", 50*mib) if err != nil && !os.IsExist(err) { return nil, fmt.Errorf("failed to create networkd cache directory: %w", err) @@ -113,14 +116,15 @@ func NewNetworker(identity *stubs.IdentityManagerStub, ndmz ndmz.DMZ, ygg *yggdr myceliumKeyDir: myceliumKey, portSet: set.NewInt(), - ygg: ygg, - ndmz: ndmz, + ygg: ygg, + mycelium: myc, + ndmz: ndmz, } - // always add the reserved yggdrasil port to the port set so we make sure they are never + // always add the reserved yggdrasil and mycelium ports to the port set so we make sure they are never // picked for wireguard endpoints // we also add http, https, and traefik metrics ports 8082 to the list. - for _, port := range []int{yggdrasil.YggListenTCP, yggdrasil.YggListenTLS, yggdrasil.YggListenLinkLocal, iperf.IperfPort, 80, 443, 8082} { + for _, port := range []int{yggdrasil.YggListenTCP, yggdrasil.YggListenTLS, yggdrasil.YggListenLinkLocal, mycelium.MyListenTCP, iperf.IperfPort, 80, 443, 8082} { if err := nw.portSet.Add(uint(port)); err != nil && errors.Is(err, set.ErrConflict{}) { return nil, err } @@ -192,9 +196,51 @@ func (n *networker) detachYgg(id string, netNs ns.NetNS) error { }) } -// prepare creates a unique namespace (based on id) with "prefix" +func (n *networker) attachMycelium(id string, netNs ns.NetNS) (net.IPNet, error) { + // new hardware address for mycelium interface + hw := ifaceutil.HardwareAddrFromInputBytes([]byte("my:" + id)) + + myc, err := n.mycelium.InspectMycelium() + if err != nil { + return net.IPNet{}, err + } + + ip, err := myc.IPFor(hw) + log.Info().Msgf("mycelium IP is %s", ip.IP) + if err != nil { + return net.IPNet{}, fmt.Errorf("failed to generate mycelium IP: %w", err) + } + + ips := []*net.IPNet{ + &ip, + } + + gw, err := myc.Gateway() + if err != nil { + return net.IPNet{}, fmt.Errorf("failed to get mycelium gateway IP: %w", err) + } + + routes := []*netlink.Route{ + { + Dst: &net.IPNet{ + IP: net.ParseIP("400::"), + Mask: net.CIDRMask(7, 128), + }, + Gw: gw.IP, + // LinkIndex:... this is set by macvlan.Install + }, + } + + if err := n.createMacVlan(ZDBMyceliumIface, types.MyceliumBridge, hw, ips, routes, netNs); err != nil { + return net.IPNet{}, errors.Wrap(err, "failed to setup zdb mycelium interface") + } + + return ip, nil +} + +// ensurePrepare ensurets that a unique namespace is created (based on id) with "prefix" // and make sure it's wired to the bridge on host namespace -func (n *networker) prepare(id, prefix, bridge string) (string, error) { +func (n *networker) ensurePrepare(id, prefix, bridge string) (string, error) { hw := ifaceutil.HardwareAddrFromInputBytes([]byte("pub:" + id)) netNSName := prefix + strings.Replace(hw.String(), ":", "", -1) @@ -209,11 +255,22 @@ func (n *networker) prepare(id, prefix, bridge string) (string, error) { return "", errors.Wrap(err, "failed to setup zdb public interface") } - if n.ygg == nil { - return netNSName, nil + if n.ygg != nil { + _, err = n.attachYgg(id, netNs) + if err != nil { + return "", err + } + + } + + if n.mycelium != nil { + _, err = n.attachMycelium(id, netNs) + if err != nil { + return "", err + } } - _, err = n.attachYgg(id, netNs) - return netNSName, err + + return netNSName, nil } func (n *networker) destroy(ns string) error { @@ -232,10 +289,10 @@ func (n *networker) destroy(ns string) error { } // func (n *networker) NSPrepare(id string, ) -// ZDBPrepare sends a macvlan interface into the +// EnsureZDBPrepare sends a macvlan interface into the // network namespace of a ZDB container -func (n *networker) ZDBPrepare(id string) (string, error) { - return n.prepare(id, zdbNamespacePrefix, types.PublicBridge) +func (n *networker) EnsureZDBPrepare(id string) (string, error) { + return n.ensurePrepare(id, zdbNamespacePrefix, types.PublicBridge) } // ZDBDestroy is the opposite of ZDPrepare, it makes sure network setup done @@ -259,7 +316,6 @@ func (n *networker) createMacVlan(iface string, master string, hw net.HardwareAd if _, ok := err.(netlink.LinkNotFoundError); ok { macVlan, err = macvlan.Create(iface, master, netNs) - if err != nil { return err } @@ -557,7 +613,7 @@ func (n *networker) SetupPubIPFilter(filterName string, iface string, ipv4 net.I return errors.Wrap(err, "failed to execute filter template") } - //TODO: use nft.Apply + // TODO: use nft.Apply cmd := exec.Command("/bin/sh", "-c", buffer.String()) output, err := cmd.CombinedOutput() @@ -999,7 +1055,7 @@ func (n *networker) SetPublicConfig(cfg pkg.PublicConfig) error { } if current != nil && current.Equal(cfg) { - //nothing to do + // nothing to do return nil } @@ -1107,7 +1163,7 @@ func (n *networker) networkOf(id zos.NetID) (nr pkg.Network, err error) { dec := json.NewDecoder(reader) version := reader.Version() - //validV1 := versioned.MustParseRange(fmt.Sprintf("=%s", pkg.NetworkSchemaV1)) + // validV1 := versioned.MustParseRange(fmt.Sprintf("=%s", pkg.NetworkSchemaV1)) validLatest := versioned.MustParseRange(fmt.Sprintf("<=%s", NetworkSchemaLatestVersion.String())) if validLatest(version) { @@ -1202,7 +1258,6 @@ func (n *networker) Metrics() (pkg.NetResourceMetrics, error) { metrics[wl] = m return nil }) - if err != nil { log.Error().Err(err).Msg("failed to collect metrics for network") } @@ -1258,7 +1313,6 @@ func (n *networker) PublicAddresses(ctx context.Context) <-chan pkg.OptionPublic } func (n *networker) ZOSAddresses(ctx context.Context) <-chan pkg.NetlinkAddresses { - var index int _ = backoff.Retry(func() error { link, err := netlink.LinkByName(types.DefaultBridge) @@ -1327,7 +1381,6 @@ func (n *networker) ZOSAddresses(ctx context.Context) <-chan pkg.NetlinkAddresse }() return ch - } func (n *networker) syncWGPorts() error { @@ -1372,7 +1425,7 @@ func (n *networker) syncWGPorts() error { log.Error().Err(err).Str("namespace", name).Msgf("failed to read port for network namespace") continue } - //skip error cause we don't care if there are some duplicate at this point + // skip error cause we don't care if there are some duplicate at this point _ = n.portSet.Add(uint(port)) } @@ -1396,7 +1449,6 @@ func createNetNS(name string) (ns.NetNS, error) { err = netNs.Do(func(_ ns.NetNS) error { return ifaceutil.SetLoUp() }) - if err != nil { _ = namespace.Delete(netNs) return nil, fmt.Errorf("failed to bring lo interface up in namespace %s: %w", name, err) diff --git a/pkg/network/types/constant.go b/pkg/network/types/constant.go index 2a1c650a6..efbe0a180 100644 --- a/pkg/network/types/constant.go +++ b/pkg/network/types/constant.go @@ -11,8 +11,10 @@ const ( // DefaultBridge is the name of the default bridge created // by the bootstrap of networkd DefaultBridge = "zos" - //PublicBridge name + // PublicBridge name PublicBridge = "br-pub" - //YggBridge ygg bridge + // YggBridge ygg bridge YggBridge = "br-ygg" + // MyceliumBridge mycelium bridge + MyceliumBridge = "br-my" ) diff --git a/pkg/primitives/zdb/zdb.go b/pkg/primitives/zdb/zdb.go index bd81d1a18..4c27d78cb 100644 --- a/pkg/primitives/zdb/zdb.go +++ b/pkg/primitives/zdb/zdb.go @@ -34,9 +34,7 @@ const ( zdbPort = 9900 ) -var ( - uuidRegex = regexp.MustCompile(`([0-9a-f]{8})\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}`) -) +var uuidRegex = regexp.MustCompile(`([0-9a-f]{8})\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}`) // ZDB types type ZDB = zos.ZDB @@ -93,9 +91,7 @@ func (p *Manager) Provision(ctx context.Context, wl *gridtypes.WorkloadWithID) ( } func (p *Manager) zdbListContainers(ctx context.Context) (map[pkg.ContainerID]tZDBContainer, error) { - var ( - contmod = stubs.NewContainerModuleStub(p.zbus) - ) + contmod := stubs.NewContainerModuleStub(p.zbus) containerIDs, err := contmod.List(ctx, zdbContainerNS) if err != nil { @@ -126,7 +122,7 @@ func (p *Manager) zdbListContainers(ctx context.Context) (map[pkg.ContainerID]tZ func (p *Manager) zdbProvisionImpl(ctx context.Context, wl *gridtypes.WorkloadWithID) (zos.ZDBResult, error) { var ( - //contmod = stubs.NewContainerModuleStub(p.zbus) + // contmod = stubs.NewContainerModuleStub(p.zbus) storage = stubs.NewStorageModuleStub(p.zbus) nsID = wl.ID.String() config ZDB @@ -217,8 +213,7 @@ func (p *Manager) zdbProvisionImpl(ctx context.Context, wl *gridtypes.WorkloadWi } func (p *Manager) ensureZdbContainer(ctx context.Context, device pkg.Device) (tZDBContainer, error) { - var container = stubs.NewContainerModuleStub(p.zbus) - + container := stubs.NewContainerModuleStub(p.zbus) name := pkg.ContainerID(device.ID) cont, err := container.Inspect(ctx, zdbContainerNS, name) @@ -237,11 +232,10 @@ func (p *Manager) ensureZdbContainer(ctx context.Context, device pkg.Device) (tZ } return tZDBContainer(cont), nil - } func (p *Manager) zdbRootFS(ctx context.Context) (string, error) { - var flist = stubs.NewFlisterStub(p.zbus) + flist := stubs.NewFlisterStub(p.zbus) var err error var rootFS string @@ -254,7 +248,6 @@ func (p *Manager) zdbRootFS(ctx context.Context) (string, error) { Limit: 10 * gridtypes.Megabyte, ReadOnly: false, }) - if err != nil { return "", errors.Wrap(err, "failed to mount zdb flist") } @@ -291,7 +284,7 @@ func (p *Manager) createZdbContainer(ctx context.Context, device pkg.Device) err } // create the network namespace and macvlan for the 0-db container - netNsName, err := network.ZDBPrepare(ctx, device.ID) + netNsName, err := network.EnsureZDBPrepare(ctx, device.ID) if err != nil { if err := flist.Unmount(ctx, string(name)); err != nil { slog.Error().Err(err).Str("path", rootFS).Msgf("failed to unmount") @@ -362,7 +355,7 @@ func (p *Manager) dataMigration(ctx context.Context, volume string) { } func (p *Manager) zdbRun(ctx context.Context, name string, rootfs string, cmd string, netns string, volumepath string, socketdir string) error { - var cont = stubs.NewContainerModuleStub(p.zbus) + cont := stubs.NewContainerModuleStub(p.zbus) // we do data migration here because this is called // on new zdb starts, or updating the runtime. @@ -423,17 +416,23 @@ func (p *Manager) waitZDBIPs(ctx context.Context, namespace string, created time if err != nil { return err } - ips = append(ips, yggIps...) + MyceliumIps, _, err := network.Addrs(ctx, nwmod.ZDBMyceliumIface, namespace) + if err != nil { + return err + } + ips = append(ips, MyceliumIps...) + var ( - public = false - ygg = false + public = false + ygg = false + mycelium = false ) containerIPs = containerIPs[:0] for _, ip := range ips { - if isPublic(ip) && !isYgg(ip) { + if isPublic(ip) && !isYgg(ip) && !isMycelium(ip) { log.Warn().IPAddr("ip", ip).Msg("0-db container public ip found") public = true containerIPs = append(containerIPs, ip) @@ -443,10 +442,15 @@ func (p *Manager) waitZDBIPs(ctx context.Context, namespace string, created time ygg = true containerIPs = append(containerIPs, ip) } + if isMycelium(ip) { + log.Warn().IPAddr("ip", ip).Msg("0-db container mycelium ip found") + mycelium = true + containerIPs = append(containerIPs, ip) + } } - log.Warn().Msgf("public %v ygg: %v", public, ygg) - if public && ygg || time.Since(created) > 2*time.Minute { + log.Warn().Msgf("public %v ygg: %v mycelium: %v", public, ygg, mycelium) + if public && ygg && mycelium || time.Since(created) > 2*time.Minute { // if we have all ips detected or if the container is older than 2 minutes // so it's safe we assume ips are final return nil @@ -768,15 +772,25 @@ var yggNet = net.IPNet{ Mask: net.CIDRMask(7, 128), } +var myceliumNet = net.IPNet{ + IP: net.ParseIP("400::"), + Mask: net.CIDRMask(7, 128), +} + func isYgg(ip net.IP) bool { return yggNet.Contains(ip) } +func isMycelium(ip net.IP) bool { + return myceliumNet.Contains(ip) +} + // InitializeZDB makes sure all required zdbs are running func (p *Manager) Initialize(ctx context.Context) error { var ( storage = stubs.NewStorageModuleStub(p.zbus) contmod = stubs.NewContainerModuleStub(p.zbus) + network = stubs.NewNetworkerStub(p.zbus) flistmod = stubs.NewFlisterStub(p.zbus) ) // fetching extected hash @@ -808,6 +822,12 @@ func (p *Manager) Initialize(ctx context.Context) error { log.Error().Err(err).Msg("failed to upgrade running zdb container") } + log.Debug().Str("container", string(container)).Msg("enusreing zdb network setup") + _, err := network.EnsureZDBPrepare(ctx, poolNames[string(container)].ID) + if err != nil { + log.Error().Err(err).Msg("failed to prepare zdb network") + } + delete(poolNames, string(container)) } @@ -827,7 +847,6 @@ func (p *Manager) upgradeRuntime(ctx context.Context, expected string, container contmod = stubs.NewContainerModuleStub(p.zbus) ) continfo, err := contmod.Inspect(ctx, zdbContainerNS, container) - if err != nil { return err } diff --git a/pkg/stubs/network_stub.go b/pkg/stubs/network_stub.go index 9f597c9a0..9482e6f07 100644 --- a/pkg/stubs/network_stub.go +++ b/pkg/stubs/network_stub.go @@ -119,6 +119,23 @@ func (s *NetworkerStub) DisconnectPubTap(ctx context.Context, arg0 string) (ret0 return } +func (s *NetworkerStub) EnsureZDBPrepare(ctx context.Context, arg0 string) (ret0 string, ret1 error) { + args := []interface{}{arg0} + result, err := s.client.RequestContext(ctx, s.module, s.object, "EnsureZDBPrepare", args...) + if err != nil { + panic(err) + } + result.PanicOnError() + ret1 = result.CallError() + loader := zbus.Loader{ + &ret0, + } + if err := result.Unmarshal(&loader); err != nil { + panic(err) + } + return +} + func (s *NetworkerStub) GetDefaultGwIP(ctx context.Context, arg0 zos.NetID) (ret0 []uint8, ret1 []uint8, ret2 error) { args := []interface{}{arg0} result, err := s.client.RequestContext(ctx, s.module, s.object, "GetDefaultGwIP", args...) @@ -706,23 +723,6 @@ func (s *NetworkerStub) ZDBDestroy(ctx context.Context, arg0 string) (ret0 error return } -func (s *NetworkerStub) ZDBPrepare(ctx context.Context, arg0 string) (ret0 string, ret1 error) { - args := []interface{}{arg0} - result, err := s.client.RequestContext(ctx, s.module, s.object, "ZDBPrepare", args...) - if err != nil { - panic(err) - } - result.PanicOnError() - ret1 = result.CallError() - loader := zbus.Loader{ - &ret0, - } - if err := result.Unmarshal(&loader); err != nil { - panic(err) - } - return -} - func (s *NetworkerStub) ZOSAddresses(ctx context.Context) (<-chan pkg.NetlinkAddresses, error) { ch := make(chan pkg.NetlinkAddresses, 1) recv, err := s.client.Stream(ctx, s.module, s.object, "ZOSAddresses")