• Kirill Smelkov's avatar
    software/ors-amarisoft: Do not recreate slaptapX-* on every idempotent `slapos node instance` run · 7989e6ce
    Kirill Smelkov authored
    To run tapsplit we use plone.recipe.command with both command and
    update-command set to `tapsplit ...`. But tapsplit, when run, currently fully
    recreates and reinitializes subtap interfaces, which leads to interfering with
    running enb because subtap interfaces, that enb started to use, are removed.
    This is not desirable behaviour.
    
    What we need:
    
    1) create subtap interfaces only once and keep them stable
    2) until configuration changes which should lead to
       * subtaps recreated, and
       * enb restarted
    3) if subtap interfaces disappear for any reason, recreate it
    
    -> Rework tapsplit to keep its promise, that it "brings tap interface into state
       with several children interfaces each covering part of original interface
       address space", without recreating those children on every run and instead
       doing any action only if their state is not what is desired.
    
    In other words those interfaces now are only created when they do not exist
    before. Addresses and routes are added only if they are not there before
    tapsplit is run, etc.
    
    After the patch the first run of tapsplit to split by 2 looks like
    
        # ./pythonwitheggs ru/tapsplit slaptap16 2
        slaptap16: split 2401:5180:0:66:a200::/71 by 2
        preserve         2401:5180:0:66:a200::/73
        -> slaptap16-1   2401:5180:0:66:a280::/73
         # ip tuntap add dev slaptap16-1 mode tap user slapuser16
         # ip link set slaptap16-1 up
         # ip addr add 2401:5180:0:66:a280::/73 dev slaptap16-1 noprefixroute
         # ip route add 2401:5180:0:66:a280::1 dev slaptap16-1
         # ip route add 2401:5180:0:66:a280::/73 dev slaptap16-1 via 2401:5180:0:66:a280::1
        -> slaptap16-2   2401:5180:0:66:a300::/73
         # ip tuntap add dev slaptap16-2 mode tap user slapuser16
         # ip link set slaptap16-2 up
         # ip addr add 2401:5180:0:66:a300::/73 dev slaptap16-2 noprefixroute
         # ip route add 2401:5180:0:66:a300::1 dev slaptap16-2
         # ip route add 2401:5180:0:66:a300::/73 dev slaptap16-2 via 2401:5180:0:66:a300::1
    
    The second run with the same arguments looks as
    
        # ./pythonwitheggs ru/tapsplit slaptap16 2
        slaptap16: split 2401:5180:0:66:a200::/71 by 2
        preserve         2401:5180:0:66:a200::/73
        -> slaptap16-1   2401:5180:0:66:a280::/73
         # slaptap16-1: already exists
         # slaptap16-1: already up
         # slaptap16-1: already has 2401:5180:0:66:a280::/73 addr
         # slaptap16-1: already has 2401:5180:0:66:a280::1 route
         # slaptap16-1: already has 2401:5180:0:66:a280::/73 route
        -> slaptap16-2   2401:5180:0:66:a300::/73
         # slaptap16-2: already exists
         # slaptap16-2: already up
         # slaptap16-2: already has 2401:5180:0:66:a300::/73 addr
         # slaptap16-2: already has 2401:5180:0:66:a300::1 route
         # slaptap16-2: already has 2401:5180:0:66:a300::/73 route
    
    where it could be seen that no actions had been taken.
    
    And if, for example, the user manipulates slaptap16-2 and manually sets it
    down, the third run restores it to desired 'UP' state and readds the address
    and routes because the kernel removed them when link went down:
    
        # ip -6 addr show dev slaptap16-2
        157: slaptap16-2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
            inet6 2401:5180:0:66:a300::/73 scope global tentative noprefixroute
               valid_lft forever preferred_lft forever
        # ip -6 route show dev slaptap16-2
        2401:5180:0:66:a300::1 metric 1024 linkdown pref medium
        2401:5180:0:66:a300::/73 via 2401:5180:0:66:a300::1 metric 1024 linkdown pref medium
        # ip link set slaptap16-2 down
        # ip -6 addr show dev slaptap16-2
        # ip -6 route show dev slaptap16-2
        # ./pythonwitheggs ru/tapsplit slaptap16 2
        slaptap16: split 2401:5180:0:66:a200::/71 by 2
        preserve         2401:5180:0:66:a200::/73
        -> slaptap16-1   2401:5180:0:66:a280::/73
         # slaptap16-1: already exists
         # slaptap16-1: already up
         # slaptap16-1: already has 2401:5180:0:66:a280::/73 addr
         # slaptap16-1: already has 2401:5180:0:66:a280::1 route
         # slaptap16-1: already has 2401:5180:0:66:a280::/73 route
        -> slaptap16-2   2401:5180:0:66:a300::/73
         # slaptap16-2: already exists
         # ip link set slaptap16-2 up
         # ip addr add 2401:5180:0:66:a300::/73 dev slaptap16-2 noprefixroute
         # ip route add 2401:5180:0:66:a300::1 dev slaptap16-2
         # ip route add 2401:5180:0:66:a300::/73 dev slaptap16-2 via 2401:5180:0:66:a300::1
    
    The first version of this patch tried to solve the problem by setting
    update-command to be noop instead of reworking tapsplit itself. But as Thomas
    noted this does not satisfy requirement "3".
    
    Amends 49ce8ef5 (software/ors-amarisoft: Provide dedicated TAP interface for each Radio Unit)
    
    /helped-by @tomo
    /cc @jhuge, @lu.xu, @xavier_thompson, @Daetalus
    /reviewed-on nexedi/slapos!1508
    7989e6ce
tapsplit 5.8 KB