Commit 7c340ab8 authored by jan.koester's avatar jan.koester
Browse files

test

parent 5a4fc205
Loading
Loading
Loading
Loading
+12 −5
Changes for include/sysbus/client.h: 12 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -70,9 +70,10 @@ constexpr const char *RestartInterface = "RestartInterface";
constexpr const char *ReloadInterface = "ReloadInterface";            // no interface: all
constexpr const char *ForceReloadInterface = "ForceReloadInterface";  // no interface: all

// Bonds, bridges and WireGuard interfaces: .netdev files in
// Bonds, bridges, VLANs and WireGuard interfaces: .netdev files in
// /etc/syslite/network; members of bonds and bridges get member .network
// files (Bond=/Bridge=), a WireGuard interface has peers. Create/Edit
// files (Bond=/Bridge=), a VLAN's parent gets VLAN= in its own .network,
// a WireGuard interface has peers. Create/Edit
// change only the files (ReloadInterface without an interface creates the
// device, adds its members, configures WireGuard); Delete also removes the
// device. Root only, except ListNetDevs (which never shows private or
@@ -148,9 +149,11 @@ struct InterfaceInfo {
    std::string configAddress; // [Network] Address=
    std::string gateway;
    std::vector<std::string> dns;
    std::string kind;          // "bond", "bridge" or "" (what the device is)
    std::string kind;          // "bond", "bridge", "vlan", "wireguard", "veth" or "" (what the device is)
    std::string master;        // the bond/bridge it is a member of now
    std::string parent;        // a VLAN: the interface it is on now
    std::string memberOf;      // configured: [Network] Bond= or Bridge=
    std::vector<std::string> vlans;  // configured: [Network] VLAN=
};

// A WireGuard peer as configured, and what the kernel knows of it.
@@ -171,16 +174,18 @@ struct WireGuardPeerInfo {
// (balance-rr, active-backup, balance-xor, broadcast, 802.3ad, balance-tlb,
// balance-alb), MII monitoring interval, LACP rate (802.3ad: slow/fast),
// transmit hash policy (layer2, layer3+4, layer2+3, ...). For a bridge:
// STP. For WireGuard: its public key, listen port, routes for the peers'
// STP. For a VLAN: its id (1-4094) and the interface it is on. For WireGuard: its public key, listen port, routes for the peers'
// AllowedIPs, peers.
struct NetDevInfo {
    std::string name;          // the interface, e.g. bond0
    std::string kind;          // bond, bridge or wireguard
    std::string kind;          // bond, bridge, vlan or wireguard
    std::string mode;
    int miimonMs = 0;
    std::string lacpRate;
    std::string hashPolicy;
    bool stp = false;
    int vlanId = 0;
    std::string parent;        // configured: the interface carrying the VLAN
    std::string publicKey;
    int listenPort = 0;        // 0: the kernel picks one
    bool routes = false;
@@ -216,6 +221,8 @@ struct NetDevSettings {
    std::optional<std::string> lacpRate;
    std::optional<std::string> hashPolicy;
    std::optional<bool> stp;
    std::optional<int> vlanId;
    std::optional<std::string> parent;   // a VLAN: the interface it is on
    std::optional<std::vector<std::string>> members;
    std::optional<std::string> privateKey;
    bool generateKey = false;
+258 −23

File changed.

Preview size limit exceeded, changes collapsed.

+36 −15
Changes for src/network.h: 36 added lines, 15 removed lines.
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ namespace syslite {
        // bridge (and gets no addresses of its own)
        std::string bond;
        std::string bridge;
        // [Network] VLAN= (repeatable): the VLANs on top of this interface
        std::vector<std::string> vlans;

        // [Link]
        bool        linkUp = true;
@@ -35,14 +37,15 @@ namespace syslite {
        std::string name;
    };

    // Parsed from systemd-networkd .netdev files: a bond, a bridge or a
    // WireGuard interface that syslite creates; the members of a bond or
    // bridge are the interfaces whose .network says Bond=<name> /
    // Bridge=<name>; a WireGuard interface has its peers instead
    // Parsed from systemd-networkd .netdev files: a bond, a bridge, an
    // 802.1Q VLAN or a WireGuard interface that syslite creates; the members
    // of a bond or bridge are the interfaces whose .network says
    // Bond=<name> / Bridge=<name>; a VLAN's parent is the interface whose
    // .network says VLAN=<name>; a WireGuard interface has its peers instead
    struct NetDevConfig {
        // [NetDev]
        std::string ifname;          // Name=bond0
        std::string kind;            // Kind=bond | bridge | wireguard
        std::string kind;            // Kind=bond | bridge | vlan | wireguard

        // [Bond]
        std::string mode = "balance-rr";   // Mode=balance-rr, active-backup, balance-xor,
@@ -54,6 +57,12 @@ namespace syslite {
        // [Bridge]
        bool        stp = false;           // STP=yes

        // [VLAN]
        int         vlanId = 0;            // Id= (1-4094)
        // not in the .netdev: the interface carrying it (VLAN= in its
        // .network); saveNetDev() writes that, vlanParent() finds it
        std::string parent;

        // [WireGuard]
        std::string wgPrivateKey;          // PrivateKey= (base64), or
        std::string wgPrivateKeyFile;      // PrivateKeyFile=
@@ -76,8 +85,9 @@ namespace syslite {
        bool        adminUp = false; // IFF_UP
        bool        carrier = false;
        bool        stopped = false; // stopped on request (stays down)
        std::string kind;            // "bond", "bridge", "wireguard" or ""
        std::string kind;            // "bond", "bridge", "vlan", "wireguard", "veth" or ""
        std::string master;          // the bond or bridge it is a member of
        std::string parent;          // a VLAN: the interface it is on
        std::vector<std::string> addresses; // "a.b.c.d/len", IPv6 too
        const NetworkConfig *config = nullptr; // first matching configuration
    };
@@ -147,19 +157,27 @@ namespace syslite {
        // Re-read the .network files only (nothing is applied)
        void reloadConfigs();

        // Bonds, bridges and WireGuard interfaces (.netdev files in
        // Bonds, bridges, VLANs and WireGuard interfaces (.netdev files in
        // ConfigDir). saveNetDev writes
        // ConfigDir/<nd.name>.netdev and makes exactly `members` its members:
        // each gets a member configuration ConfigDir/10-<member>.network
        // (Bond=/Bridge=), former members lose theirs. deleteNetDev removes
        // the file, the member configurations and the device itself. Both
        // re-read the files; applyNetDevs() (also part of applyAll/reload)
        // creates what is missing and configures the WireGuard interfaces.
        // A WireGuard .netdev holds its private key: written 0600, and
        // saveNetDev generates one if nd has none.
        // (Bond=/Bridge=), former members lose theirs. A VLAN has no members
        // but nd.parent: the parent's own configuration (10-<parent>, a copy
        // of the one that applies to it now if it has none) gets VLAN=, a
        // former parent loses it. deleteNetDev removes the file, the member
        // configurations and the device itself (a bond or bridge carrying
        // VLANs only once they are gone). Both re-read the files;
        // applyNetDevs() (also part of applyAll/reload) creates what is
        // missing (VLANs last, on their parents) and configures the
        // WireGuard interfaces. A WireGuard .netdev holds its private key:
        // written 0600, and saveNetDev generates one if nd has none.
        const std::vector<NetDevConfig> &netDevs() const { return _netdevs; }
        const NetDevConfig *findNetDev(const std::string &ifname) const;
        std::vector<std::string> membersOf(const std::string &ifname) const;
        // the interface whose (applying) configuration says VLAN=ifname ("": none)
        std::string vlanParent(const std::string &ifname) const;
        // the VLANs (.netdev) on ifname
        std::vector<std::string> vlansOn(const std::string &ifname) const;
        bool saveNetDev(const NetDevConfig &nd, const std::vector<std::string> &members, std::string *err);
        bool deleteNetDev(const std::string &ifname, std::string *err);
        void applyNetDevs();
@@ -192,6 +210,8 @@ namespace syslite {
        bool parseNetDevFile(const std::string &path, NetDevConfig &nd);
        bool writeNetDevFile(const NetDevConfig &nd, std::string *err);
        bool writeNetworkFile(const NetworkConfig &cfg, std::string *err);
        // VLAN=<nd.ifname> into nd.parent's own .network (out of the others)
        bool writeVlanParent(const NetDevConfig &nd, std::string *err);

        // Netlink: create a bond/bridge (RTM_NEWLINK with IFLA_LINKINFO),
        // delete a link, make ifname a member of master ("": none)
@@ -201,7 +221,8 @@ namespace syslite {
        // fixes ifname's MAC address ("aa:bb:cc:dd:ee:ff"; a bridge keeps it
        // instead of following its ports)
        bool setLinkAddress(const std::string &ifname, const std::string &mac);
        // does the existing device match nd (kind, bond mode, STP)?
        // does the existing device match nd (kind, bond mode, STP, VLAN
        // id and parent)?
        bool linkMatches(const NetDevConfig &nd);
        // WireGuard: keys, port and peers into the kernel; routes for the
        // peers' AllowedIPs (RouteTable=main; once the link is up)
@@ -257,7 +278,7 @@ namespace syslite {
        std::map<std::string, std::vector<std::string>> _dnsByIf; // DNS servers per interface
        std::set<std::string> _configured; // interfaces configureInterface() set up
        std::set<std::string> _stopped;    // interfaces stopped on request
        std::set<std::string> _createdLinks;  // bonds/bridges created by applyNetDevs
        std::set<std::string> _createdLinks;  // bonds/bridges/VLANs created by applyNetDevs
        std::map<std::string, std::string> _netDevErrors;  // applyNetDevs() failures by ifname
        bool _resolvWritten = false;       // resolv.yaml is ours once written
        int _monitorFd = -1;
+6 −0
Changes for src/sysbus/client.cpp: 6 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -74,7 +74,9 @@ InterfaceInfo interfaceFromFields(const std::vector<std::pair<std::string, std::
        else if (k == "dns") i.dns.push_back(v);
        else if (k == "kind") i.kind = v;
        else if (k == "master") i.master = v;
        else if (k == "parent") i.parent = v;
        else if (k == "member_of") i.memberOf = v;
        else if (k == "vlan") i.vlans.push_back(v);
    }
    return i;
}
@@ -90,6 +92,8 @@ NetDevInfo netDevFromFields(const std::vector<std::pair<std::string, std::string
        else if (k == "lacp_rate") n.lacpRate = v;
        else if (k == "hash_policy") n.hashPolicy = v;
        else if (k == "stp") n.stp = v == "yes";
        else if (k == "vlan_id") n.vlanId = std::atoi(v.c_str());
        else if (k == "parent") n.parent = v;
        else if (k == "config") n.config = v;
        else if (k == "config_path") n.configPath = v;
        else if (k == "exists") n.exists = v == "yes";
@@ -356,6 +360,8 @@ static std::vector<std::pair<std::string, std::string>> netDevArgs(const NetDevS
    if (s.lacpRate) a.emplace_back("lacp_rate", *s.lacpRate);
    if (s.hashPolicy) a.emplace_back("hash_policy", *s.hashPolicy);
    if (s.stp) a.emplace_back("stp", *s.stp ? "yes" : "no");
    if (s.vlanId) a.emplace_back("vlan_id", std::to_string(*s.vlanId));
    if (s.parent) a.emplace_back("parent", *s.parent);
    if (s.members) {
        a.emplace_back("set_members", "yes");  // also when empty: no members
        for (auto &m : *s.members) a.emplace_back("member", m);
+8 −1
Changes for src/syslite.cpp: 8 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -388,6 +388,7 @@ namespace syslite {
        m.add("stopped", st.stopped ? "yes" : "no");
        if (!st.kind.empty()) m.add("kind", st.kind);
        if (!st.master.empty()) m.add("master", st.master);
        if (!st.parent.empty()) m.add("parent", st.parent);
        for (auto &a : st.addresses) m.add("address", a);
        if (const NetworkConfig *cfg = st.config) {
            m.add("config", cfg->name);
@@ -399,6 +400,7 @@ namespace syslite {
            for (auto &d : cfg->dns) m.add("dns", d);
            if (!cfg->bond.empty()) m.add("member_of", cfg->bond);
            else if (!cfg->bridge.empty()) m.add("member_of", cfg->bridge);
            for (auto &v : cfg->vlans) m.add("vlan", v);
        }
    }

@@ -479,7 +481,7 @@ namespace syslite {
            if (call.has("set_dns")) cfg.dns = call.getAll("dns");
            if (cfg.matchName.empty())
                return Message::error(call, err::InvalidArgs, "a configuration needs a match (interface name or pattern)");
            if (!cfg.dhcp && cfg.address.empty() && cfg.bond.empty() && cfg.bridge.empty())
            if (!cfg.dhcp && cfg.address.empty() && cfg.bond.empty() && cfg.bridge.empty() && cfg.vlans.empty())
                return Message::error(call, err::InvalidArgs, "a configuration without DHCP needs an address");
            return done(_network.saveConfig(cfg, &why), {});
        }
@@ -518,6 +520,9 @@ namespace syslite {
                    if (!nd.hashPolicy.empty()) r.add("hash_policy", nd.hashPolicy);
                } else if (nd.kind == "bridge") {
                    r.add("stp", nd.stp ? "yes" : "no");
                } else if (nd.kind == "vlan") {
                    r.add("vlan_id", std::to_string(nd.vlanId));
                    r.add("parent", nd.parent);
                } else {
                    // never the private or preshared keys: this is open to everyone
                    r.add("public_key", _network.wireGuardPublicKey(nd));
@@ -601,6 +606,8 @@ namespace syslite {
        if (call.has("lacp_rate")) nd.lacpRate = call.get("lacp_rate");
        if (call.has("hash_policy")) nd.hashPolicy = call.get("hash_policy");
        if (call.has("stp")) nd.stp = call.get("stp") == "yes";
        if (call.has("vlan_id")) nd.vlanId = std::atoi(call.get("vlan_id").c_str());
        if (call.has("parent")) nd.parent = call.get("parent");
        if (call.has("set_members")) members = call.getAll("member");
        if (nd.kind == "wireguard") {
            if (call.has("private_key")) {