1. 07 May, 2019 5 commits
    • Thomas Haller's avatar
      libnm: rename "memory" parameter of fq_codel QDisc to "memory_limit" · 666d5880
      Thomas Haller authored
      Kernel calls the netlink attribute TCA_FQ_CODEL_MEMORY_LIMIT. Likewise,
      iproute2 calls this "memory_limit".
      
      Rename because TC parameters are inherrently tied to the kernel
      implementation and we should use the familiar name.
      666d5880
    • Thomas Haller's avatar
      platform: fix handling of default value for TCA_FQ_CODEL_CE_THRESHOLD · 973db2d4
      Thomas Haller authored
      iproute2 uses the special value ~0u to indicate not to set
      TCA_FQ_CODEL_CE_THRESHOLD in RTM_NEWQDISC. When not explicitly
      setting the value, kernel treats the threshold as disabled.
      
      However note that 0xFFFFFFFFu is not an invalid threshold (as far as
      kernel is concerned). Thus, we should not use that as value to indicate
      that the value is unset. Note that iproute2 uses the special value ~0u
      only internally thereby making it impossible to set the threshold to
      0xFFFFFFFFu). But kernel does not have this limitation.
      
      Maybe the cleanest way would be to add another field to NMPlatformQDisc:
      
          guint32 ce_threshold;
          bool ce_threshold_set:1;
      
      that indicates whether the threshold is enable or not.
      But note that kernel does:
      
          static void codel_params_init(struct codel_params *params)
          {
          ...
                  params->ce_threshold = CODEL_DISABLED_THRESHOLD;
      
          static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
                                     struct netlink_ext_ack *extack)
          {
          ...
                  if (tb[TCA_FQ_CODEL_CE_THRESHOLD]) {
                          u64 val = nla_get_u32(tb[TCA_FQ_CODEL_CE_THRESHOLD]);
      
                          q->cparams.ce_threshold = (val * NSEC_PER_USEC) >> CODEL_SHIFT;
                  }
      
          static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb)
          {
          ...
                  if (q->cparams.ce_threshold != CODEL_DISABLED_THRESHOLD &&
                      nla_put_u32(skb, TCA_FQ_CODEL_CE_THRESHOLD,
                                  codel_time_to_us(q->cparams.ce_threshold)))
                          goto nla_put_failure;
      
      This means, kernel internally uses the special value 0x83126E97u to indicate
      that the threshold is disabled (WTF). That is because
      
        (((guint64) 0x83126E97u) * NSEC_PER_USEC) >> CODEL_SHIFT == CODEL_DISABLED_THRESHOLD
      
      So in kernel API this value is reserved (and has a special meaning
      to indicate that the threshold is disabled). So, instead of adding a
      ce_threshold_set flag, use the same value that kernel anyway uses.
      973db2d4
    • Thomas Haller's avatar
      platform: fix handling of fq_codel's memory limit default value · 46a90438
      Thomas Haller authored
      The memory-limit is an unsigned integer. It is ugly (if not wrong) to compare unsigned
      values with "-1". When comparing with the default value we must also use an u32 type.
      Instead add a define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET.
      
      Note that like iproute2 we treat NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET
      to indicate to not set TCA_FQ_CODEL_MEMORY_LIMIT in RTM_NEWQDISC. This
      special value is entirely internal to NetworkManager (or iproute2) and
      kernel will then choose a default memory limit (of 32MB). So setting
      NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET means to leave it to kernel to
      choose a value (which then chooses 32MB).
      
      See kernel's net/sched/sch_fq_codel.c:
      
          static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
                                   struct netlink_ext_ack *extack)
          {
          ...
                  q->memory_limit = 32 << 20; /* 32 MBytes */
      
          static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
                                     struct netlink_ext_ack *extack)
          ...
                  if (tb[TCA_FQ_CODEL_MEMORY_LIMIT])
                          q->memory_limit = min(1U << 31, nla_get_u32(tb[TCA_FQ_CODEL_MEMORY_LIMIT]));
      
      Note that not having zero as default value is problematic. In fields like
      "NMPlatformIP4Route.table_coerced" and "NMPlatformRoutingRule.suppress_prefixlen_inverse"
      we avoid this problem by storing a coerced value in the structure so that zero is still
      the default. We don't do that here for memory-limit, so the caller must always explicitly
      set the value.
      46a90438
    • Thomas Haller's avatar
      platform: use u32 netlink type for TCA_FQ_CODEL_ECN · a1099a1f
      Thomas Haller authored
      In practice, there is no difference when representing 0 or 1 as signed/unsigned 32
      bit integer. But still use the correct type that also kernel uses.
      
      Also, the implicit conversation from uint32 to bool was correct already.
      Still, explicitly convert the uint32 value to boolean in _new_from_nl_qdisc().
      It's no change in behavior.
      a1099a1f
    • Thomas Haller's avatar
      platform/ethtool,mii: retry ioctl when interface name was renamed for ehttool/mii · 85632256
      Thomas Haller authored
      ethtool/mii API is based on the ifname. As an interface can be renamed,
      this API is inherently racy. We would prefer to use the ifindex instead.
      The ifindex of a device cannot change (altough it can repeat, which opens a
      different race *sigh*).
      
      Anyway, we were already trying to minimize the race be resolving the
      name from ifindex immediately before the call to ethtool/mii.
      
      Do better than that. Now resolve the name before and after the call. If
      the name changed in the meantime, we have an indication that a race
      might have happend (but we cannot be sure).
      
      Note that this can not catch every possible kind of rename race. If you are very
      unlucky a swapping of names cannot be detected.
      
      For getters this is relatively straight forward. Just retry when we
      have an indication to fall victim to a race (up to a few times). Yes, we
      still cannot be 100% sure, but this should be very reliable in practice.
      
      For setters (that modify the device) we also retry. We do so under the
      assumption that setting the same options multiple times has no bad effect.
      Note that for setters the race of swapping interface names is particularly
      bad. If we hit a very unlucky race condition, we might set the setting on
      the wrong interface and there is nothing we can do about it. The retry only
      ensures that eventually we will set it on the right interface.
      
      Note that this involves one more if_indextoname() call for each operation (in
      the common case when there is no renaming race). In cases where we make
      multiple ioctl calls, we cache and reuse the information though. So, for such
      calls the overhead is even smaller.
      85632256
  2. 30 Apr, 2019 2 commits
  3. 18 Apr, 2019 18 commits
    • Thomas Haller's avatar
      shared: move most of "shared/nm-utils" to "shared/nm-glib-aux" · d984b2ce
      Thomas Haller authored
      From the files under "shared/nm-utils" we build an internal library
      that provides glib-based helper utilities.
      
      Move the files of that basic library to a new subdirectory
      "shared/nm-glib-aux" and rename the helper library "libnm-core-base.la"
      to "libnm-glib-aux.la".
      
      Reasons:
      
       - the name "utils" is overused in our code-base. Everything's an
         "utils". Give this thing a more distinct name.
      
       - there were additional files under "shared/nm-utils", which are not
         part of this internal library "libnm-utils-base.la". All the files
         that are part of this library should be together in the same
         directory, but files that are not, should not be there.
      
       - the new name should better convey what this library is and what is isn't:
         it's a set of utilities and helper functions that extend glib with
         funcitonality that we commonly need.
      
      There are still some files left under "shared/nm-utils". They have less
      a unifying propose to be in their own directory, so I leave them there
      for now. But at least they are separate from "shared/nm-glib-aux",
      which has a very clear purpose.
      
      (cherry picked from commit 80db06f7)
      d984b2ce
    • Thomas Haller's avatar
      shared: move udev helper to separate directory "shared/nm-udev-aux" · 95621586
      Thomas Haller authored
      We built (among others) two libraries from the sources in "shared/nm-utils":
      "libnm-utils-base.la" and "libnm-utils-udev.la".
      
      It's confusing. Instead use directories so there is a direct
      correspondence between these internal libraries and the source files.
      
      (cherry picked from commit 2973d682)
      95621586
    • Thomas Haller's avatar
      shared: split C-only helper "shared/nm-std-aux" utils out of "shared/nm-utils" · 0a6f21fb
      Thomas Haller authored
      "shared/nm-utils" contains general purpose utility functions that only
      depend on glib (and extend glib with some helper functions).
      
      We will also add code that does not use glib, hence it would be good
      if the part of "shared/nm-utils" that does not depend on glib, could be
      used by these future projects.
      
      Also, we use the term "utils" everywhere. While that covers the purpose
      and content well, having everything called "nm-something-utils" is not
      great. Instead, call this "nm-std-aux", inspired by "c-util/c-stdaux".
      
      (cherry picked from commit b434b9ec)
      0a6f21fb
    • Thomas Haller's avatar
      shared: move most of "shared/nm-utils" to "shared/nm-glib-aux" · 80db06f7
      Thomas Haller authored
      From the files under "shared/nm-utils" we build an internal library
      that provides glib-based helper utilities.
      
      Move the files of that basic library to a new subdirectory
      "shared/nm-glib-aux" and rename the helper library "libnm-core-base.la"
      to "libnm-glib-aux.la".
      
      Reasons:
      
       - the name "utils" is overused in our code-base. Everything's an
         "utils". Give this thing a more distinct name.
      
       - there were additional files under "shared/nm-utils", which are not
         part of this internal library "libnm-utils-base.la". All the files
         that are part of this library should be together in the same
         directory, but files that are not, should not be there.
      
       - the new name should better convey what this library is and what is isn't:
         it's a set of utilities and helper functions that extend glib with
         funcitonality that we commonly need.
      
      There are still some files left under "shared/nm-utils". They have less
      a unifying propose to be in their own directory, so I leave them there
      for now. But at least they are separate from "shared/nm-glib-aux",
      which has a very clear purpose.
      80db06f7
    • Thomas Haller's avatar
      shared: move udev helper to separate directory "shared/nm-udev-aux" · 2973d682
      Thomas Haller authored
      We built (among others) two libraries from the sources in "shared/nm-utils":
      "libnm-utils-base.la" and "libnm-utils-udev.la".
      
      It's confusing. Instead use directories so there is a direct
      correspondence between these internal libraries and the source files.
      2973d682
    • Thomas Haller's avatar
      shared: split C-only helper "shared/nm-std-aux" utils out of "shared/nm-utils" · b434b9ec
      Thomas Haller authored
      "shared/nm-utils" contains general purpose utility functions that only
      depend on glib (and extend glib with some helper functions).
      
      We will also add code that does not use glib, hence it would be good
      if the part of "shared/nm-utils" that does not depend on glib, could be
      used by these future projects.
      
      Also, we use the term "utils" everywhere. While that covers the purpose
      and content well, having everything called "nm-something-utils" is not
      great. Instead, call this "nm-std-aux", inspired by "c-util/c-stdaux".
      b434b9ec
    • Thomas Haller's avatar
      platform: detect kernel support for FRA_L3MDEV · a9cf54c4
      Thomas Haller authored
      (cherry picked from commit eba4fd56)
      a9cf54c4
    • Thomas Haller's avatar
      platform: detect kernel support for FRA_UID_RANGE · ff686dd6
      Thomas Haller authored
      (cherry picked from commit 1dd1dcb8)
      ff686dd6
    • Thomas Haller's avatar
      41275831
    • Thomas Haller's avatar
      platform: detect kernel support for FRA_PROTOCOL · 6bfce358
      Thomas Haller authored
      (cherry picked from commit cd62d439)
      6bfce358
    • Thomas Haller's avatar
      platform: refactor detecting kernel features · bf36fa11
      Thomas Haller authored
      Next we will need to detect more kernel features. First refactor the
      handling of these to require less code changes and be more efficient.
      A plain nm_platform_kernel_support_get() only reqiures to access an
      array in the common case.
      
      The other important change is that the function no longer requires a
      NMPlatform instance. This allows us to check kernel support from
      anywhere. The only thing is that we require kernel support to be
      initialized before calling this function. That means, an NMPlatform
      instance must have detected support before.
      
      (cherry picked from commit ee269b31)
      bf36fa11
    • Thomas Haller's avatar
      eba4fd56
    • Thomas Haller's avatar
      1dd1dcb8
    • Thomas Haller's avatar
    • Thomas Haller's avatar
      cd62d439
    • Thomas Haller's avatar
      platform: refactor detecting kernel features · ee269b31
      Thomas Haller authored
      Next we will need to detect more kernel features. First refactor the
      handling of these to require less code changes and be more efficient.
      A plain nm_platform_kernel_support_get() only reqiures to access an
      array in the common case.
      
      The other important change is that the function no longer requires a
      NMPlatform instance. This allows us to check kernel support from
      anywhere. The only thing is that we require kernel support to be
      initialized before calling this function. That means, an NMPlatform
      instance must have detected support before.
      ee269b31
    • Beniamino Galvani's avatar
      all: support bridge vlan ranges · da204257
      Beniamino Galvani authored
      In some cases it is convenient to specify ranges of bridge vlans, as
      already supported by iproute2 and natively by kernel. With this commit
      it becomes possible to add a range in this way:
      
       nmcli connection modify eth0-slave +bridge-port.vlans "100-200 untagged"
      
      vlan ranges can't be PVIDs because only one PVID vlan can exist.
      
      https://bugzilla.redhat.com/show_bug.cgi?id=1652910
      (cherry picked from commit 70935157)
      da204257
    • Beniamino Galvani's avatar
      all: support bridge vlan ranges · 70935157
      Beniamino Galvani authored
      In some cases it is convenient to specify ranges of bridge vlans, as
      already supported by iproute2 and natively by kernel. With this commit
      it becomes possible to add a range in this way:
      
       nmcli connection modify eth0-slave +bridge-port.vlans "100-200 untagged"
      
      vlan ranges can't be PVIDs because only one PVID vlan can exist.
      
      https://bugzilla.redhat.com/show_bug.cgi?id=1652910
      70935157
  4. 10 Apr, 2019 1 commit
  5. 04 Apr, 2019 2 commits
  6. 27 Mar, 2019 1 commit
  7. 26 Mar, 2019 2 commits
  8. 13 Mar, 2019 6 commits
    • Thomas Haller's avatar
      9992ac1c
    • Thomas Haller's avatar
      platform: add support for routing-rule objects and cache them in platform · 9934a6a0
      Thomas Haller authored
      Add and implement NMPlatformRoutingRule types and let the platform cache
      handle rules.
      
      Rules are special in two ways:
      
      - they don't have an ifindex. That makes them different from all other
        currently existing NMPlatform* types, which have an "ifindex" field and
        "implement" NMPlatformObjWithIfindex.
      
      - they have an address family, but contrary to addresses and routes, there
        is only one NMPlatformRoutingRule object to handle both address
        families.
      
      Both of these points require some special considerations.
      
      Kernel treats routing-rules quite similar to routes. That is, kernel
      allows to add different rules/routes, as long as they differ in certain
      fields. These "fields" make up the identity of the rules/routes. But
      in practice, it's not defined which fields contribute to the identity
      of these objects. That makes using the netlink API very hard. For
      example, when kernel gains support for a new attribute which
      NetworkManager does not know yet, then users can add two rules/routes
      that look the same to NetworkManager. That can easily result in cache
      inconsistencies.
      
      Another problem is, that older kernel versions may not yet support all
      fields, which NetworkManager (and newer kernels) considers for identity.
      The older kernel will not simply reject netlink messages with these unknown
      keys, instead it will proceed adding the route/rule without it. That means,
      the added route/rule will have a different identity than what NetworkManager
      intended to add.
      9934a6a0
    • Thomas Haller's avatar
      platform: separate the refresh-type from the object type · b9ee40b8
      Thomas Haller authored
      Currently, there is a directy one to one relation between
      
       - DELAYED_ACTION_TYPE_REFRESH_ALL_*
      
       - REFRESH_ALL_TYPE_*
      
       - NMP_OBJECT_TYPE_*
      
      For IP addresses, routes and routing policy rules, when we request
      a refresh-all (NLM_F_DUMP), we want to specify the address family.
      
      For addresses and routes that is currently solved by having two
      sets of NMPObject types, for each address family one.
      
      I think that is cumbersome because the implementations of both address
      families are quite similar. By implementing both families as different
      object types, we have a lot of duplicate code and it's hard to see where
      the families actually differ. It would be better to have only one NMPObject
      type, but then when we "refresh-all" such types, we still want to be able
      to dump all (AF_UNSPEC) or only a particular address family (AF_INET, AF_INET6).
      
      Decouple REFRESH_ALL_TYPE_* from NMP_OBJECT_TYPE_* to make that
      possible.
      b9ee40b8
    • Thomas Haller's avatar
      platform/trivial: rename enum DELAYED_ACTION_IDX_REFRESH_ALL_* to REFRESH_ALL_TYPE_* · 0a2a8617
      Thomas Haller authored
      While these numbers are strongly related to DELAYED_ACTION_TYPE_REFRESH_ALL_*,
      they differ in their meaning.
      
      These are the refresh-all-types that we support. While some of the delayed-actions
      are indeed for refresh-all, they are not the same thing.
      
      Rename the enum.
      0a2a8617
    • Thomas Haller's avatar
      platform: drop unused nm_platform_refresh_all() · 7c5ad2d9
      Thomas Haller authored
      The function is unused. It would require redesign to work with
      future changes, and since it's unused, just drop it.
      
      The long reasoning is:
      
          Currently, a refresh-all is tied to an NMPObjectType. However, with
          NMPObjectRoutingRule (for policy-routing-rules) that will no longer
          be the case.
      
          That is because NMPObjectRoutingRule will be one object type for
          AF_INET and AF_INET6. Contrary to IPv4 addresses and routes, where
          there are two sets of NMPObject types.
      
          The reason is, that it's preferable to treat IPv4 and IPv6 objects
          similarly, that is: as the same type with an address family property.
      
          That also follows netlink, which uses RTM_GET* messages for both
          address families, and the address family is expressed inside the
          message.
      
          But then an API like nm_platform_refresh_all() makes little sense,
          it would require at least an addr_family argument. But since the
          API is unused, just drop it.
      7c5ad2d9
    • Thomas Haller's avatar
      platform: suppress unnecessary logging in do_request_all_no_delayed_actions() · bbfb8a9b
      Thomas Haller authored
      When we refresh all links, we clear all flags to refresh a specific
      link. However, only log a message if there was anything to clear.
      bbfb8a9b
  9. 07 Mar, 2019 3 commits