diff --git a/README.md b/README.md index 2690553..7d67ea9 100644 --- a/README.md +++ b/README.md @@ -3,25 +3,22 @@ This is an SNMP agent that implements the [Agentx](https://datatracker.ietf.org/doc/html/rfc2257) protocol. It connects to VPP's `statseg` (statistics memory segment) by MMAPing it, so the user running the agent must have read access to `/run/vpp/stats.sock`. -It then connects to SNMP's `agentx` socket, which can be either a TCP socket -(by default localhost:705), or a unix domain socket (by default /var/agentx/master) -the latter being readable only by root. It's preferable to run as unprivileged user +It also connects to VPP's API endpoint, so the user running the agent must +have read/write access to `/run/vpp/api.sock`. Both of these are typically accomplished +by running the agent as group `vpp`. -The agent incorporates [pyagentx](https://github.com/hosthvo/pyagentx) with a few -changes, and is released with the BSD 2-clause license. +The agent connects to SNMP's `agentx` socket, which can be either a TCP socket +(by default `localhost:705`), or a unix domain socket (by default `/var/agentx/master`) +the latter being readable only by root. It's preferable to run as unprivileged user, +so a TCP socket is preferred (and the default). -## Running +The agent incorporates a refactored/modified [pyagentx](https://github.com/hosthvo/pyagentx). +The upstream pyagentx code uses a threadpool and message queue, but it was not very stable. +Often, due to lack of proper locking, updaters would overwrite parts of the MIB and as a +result, any reads that were ongoing would abruptly be truncated. I refactored the code to +be single-threaded, greatly simplifying the design (and eliminating the need for locking). -First, configure the snmpd to accept agentx connections by adding the following -to `snmpd.conf`: -``` -master agentx -agentXSocket tcp:localhost:705,unix:/var/agentx-dataplane/master -``` - -and restart snmpd to pick up the changes. Simply run `./vpp-snmp-agent.py` and it -will connect to the snmpd on localhost:705, and expose the IFMib by periodically -polling VPP. Observe the console output. +To respect the original authors, this code is released with the same BSD 2-clause license. ## Building @@ -45,14 +42,34 @@ optional arguments: sudo cp dist/vpp-snmp-agent /usr/sbin/ ``` +## SNMPd config + +First, configure the snmpd to accept agentx connections by adding (at least) the following +to `snmpd.conf`: +``` +master agentx +agentXSocket tcp:localhost:705,unix:/var/agentx-dataplane/master +``` + +and restart snmpd to pick up the changes. Simply run `./vpp-snmp-agent.py` and it +will connect to the snmpd on localhost:705, and expose the IFMib by periodically +polling VPP. Observe the console output. + + ## Running in production -Meant to be run on Ubuntu, copy `vpp-snmp-agent.service`, enable and start: +Meant to be run on Ubuntu, copy `*.service`, disable the main snmpd, enable +the one that runs in the dataplane network namespace and start it all up: ``` +sudo cp netns-dataplane.service /usr/lib/systemd/system/ sudo cp snmpd-dataplane.service /usr/lib/systemd/system/ sudo cp vpp-snmp-agent.service /usr/lib/systemd/system/ sudo systemctl daemon-reload +sudo systemctl stop snmpd +sudo systemctl disable snmpd +sudo systemctl enable netns-dataplane +sudo systemctl start netns-dataplane sudo systemctl enable snmpd-dataplane sudo systemctl start snmpd-dataplane sudo systemctl enable vpp-snmp-agent diff --git a/netns-dataplane.service b/netns-dataplane.service new file mode 100644 index 0000000..ec3fe83 --- /dev/null +++ b/netns-dataplane.service @@ -0,0 +1,31 @@ +[Unit] +Description=Dataplane network namespace +After=systemd-sysctl.service network-pre.target +Before=network.target network-online.target + +[Service] +Type=oneshot +RemainAfterExit=yes + +# PrivateNetwork will create network namespace which can be +# used in JoinsNamespaceOf=. +PrivateNetwork=yes + +# To set `ip netns` name for this namespace, we create a second namespace +# with required name, unmount it, and then bind our PrivateNetwork +# namespace to it. After this we can use our PrivateNetwork as a named +# namespace in `ip netns` commands. +ExecStartPre=-/usr/bin/echo "Creating dataplane network namespace" +ExecStart=-/usr/sbin/ip netns delete dataplane +ExecStart=-/usr/bin/mkdir -p /etc/netns/dataplane +ExecStart=-/usr/bin/touch /etc/netns/dataplane/resolv.conf +ExecStart=-/usr/sbin/ip netns add dataplane +ExecStart=-/usr/bin/umount /var/run/netns/dataplane +ExecStart=-/usr/bin/mount --bind /proc/self/ns/net /var/run/netns/dataplane +# Apply default sysctl for dataplane namespace +ExecStart=-/usr/sbin/ip netns exec dataplane /usr/lib/systemd/systemd-sysctl +ExecStop=-/usr/sbin/ip netns delete dataplane + +[Install] +WantedBy=multi-user.target +WantedBy=network-online.target