[systemd-devel] [PATCH 04/11] sd-icmp6-nd: Add link and prefix structures for ICMPv6

Tom Gundersen teg at jklm.no
Wed Jan 14 05:03:41 PST 2015


On Tue, Jan 13, 2015 at 1:02 PM, Patrik Flykt
<patrik.flykt at linux.intel.com> wrote:
> Each ICMPv6 structure has an interface index and will therefore be
> associated with an IPv6 link containing a list of of prefixes.
> ---
>  src/libsystemd-network/sd-icmp6-nd.c | 99 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 99 insertions(+)
>
> diff --git a/src/libsystemd-network/sd-icmp6-nd.c b/src/libsystemd-network/sd-icmp6-nd.c
> index c9b390e..35d5f5f 100644
> --- a/src/libsystemd-network/sd-icmp6-nd.c
> +++ b/src/libsystemd-network/sd-icmp6-nd.c
> @@ -44,6 +44,23 @@ enum icmp6_nd_state {
>  #define ICMP6_ND_RECV_SIZE (IP6_MIN_MTU - sizeof(struct ip6_hdr))
>  #define ICMP6_OPT_LEN_UNITS 8
>
> +struct icmp6_prefix {
> +        RefCount n_ref;
> +
> +        LIST_FIELDS(struct icmp6_prefix, prefixes);
> +
> +        uint8_t len;
> +        sd_event_source *timeout_valid;
> +        struct in6_addr addr;
> +};

Structs that we don't export we usually use CamelCase for the name (and typedef)

So

typedef ICMP6Prefix {
    ...
} ICMP6Prefix;

> +struct icmp6_link {
> +        RefCount n_ref;
> +
> +        uint32_t mtu;
> +        LIST_HEAD(struct icmp6_prefix, prefixes);
> +};
> +
>  struct sd_icmp6_nd {
>          RefCount n_ref;
>
> @@ -52,6 +69,7 @@ struct sd_icmp6_nd {
>          int event_priority;
>          int index;
>          struct ether_addr mac_addr;
> +        struct icmp6_link *link;

This looks a bit strange to me. The sd_icmp6_nd struct is anyway
per-link, so why not just embed the members from icmp6_link directly
in sd_icmp6_nd?

>          int fd;
>          sd_event_source *recv;
>          sd_event_source *timeout;
> @@ -62,6 +80,72 @@ struct sd_icmp6_nd {
>
>  #define log_icmp6_nd(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "ICMPv6 CLIENT: " fmt, ##__VA_ARGS__)
>
> +static struct icmp6_prefix *icmp6_prefix_unref(struct icmp6_prefix *prefix) {
> +        if (prefix && REFCNT_DEC(prefix->n_ref) <= 0) {
> +                prefix->timeout_valid =
> +                        sd_event_source_unref(prefix->timeout_valid);
> +
> +                free(prefix);
> +        }
> +
> +        return NULL;
> +}
> +
> +static int icmp6_prefix_new(struct icmp6_prefix **ret) {
> +        _cleanup_free_ struct icmp6_prefix *prefix = NULL;
> +
> +        assert(ret);
> +
> +        prefix = new0(struct icmp6_prefix, 1);
> +        if (!prefix)
> +                return -ENOMEM;
> +
> +        prefix->n_ref = REFCNT_INIT;
> +        LIST_INIT(prefixes, prefix);
> +
> +        *ret = prefix;
> +        prefix = NULL;
> +
> +        return 0;
> +}
> +
> +static struct icmp6_link *icmp6_link_unref(struct icmp6_link *link) {
> +        if (link && REFCNT_DEC(link->n_ref) <= 0) {
> +                struct icmp6_prefix *prefix, *p;
> +
> +                LIST_FOREACH_SAFE(prefixes, prefix, p, link->prefixes) {
> +                        LIST_REMOVE(prefixes, link->prefixes, prefix);
> +
> +                        prefix = icmp6_prefix_unref(prefix);
> +                }
> +                free(link);
> +        }
> +
> +        return NULL;
> +}
> +
> +DEFINE_TRIVIAL_CLEANUP_FUNC(struct icmp6_link*, icmp6_link_unref);
> +#define _cleanup_icmp6_link_free_ _cleanup_(icmp6_link_unrefp)
> +
> +static int icmp6_link_new(struct icmp6_link **ret) {
> +        _cleanup_free_ struct icmp6_link *link = NULL;
> +
> +        assert(ret);
> +
> +        link = new0(struct icmp6_link, 1);
> +        if (!link)
> +                return -ENOMEM;
> +
> +        link->n_ref = REFCNT_INIT;
> +
> +        LIST_HEAD_INIT(link->prefixes);
> +
> +        *ret = link;
> +        link = NULL;
> +
> +        return 0;
> +}
> +
>  static void icmp6_nd_notify(sd_icmp6_nd *nd, int event)
>  {
>          if (nd->callback)
> @@ -156,6 +240,8 @@ sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd) {
>                  icmp6_nd_init(nd);
>                  sd_icmp6_nd_detach_event(nd);
>
> +                nd->link = icmp6_link_unref(nd->link);
> +
>                  free(nd);
>          }
>
> @@ -191,6 +277,7 @@ static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,
>          struct nd_opt_hdr *opt_hdr;
>
>          assert_return(nd, -EINVAL);
> +        assert_return(nd->link, -EINVAL);
>          assert_return(ra, -EINVAL);
>
>          len -= sizeof(*ra);
> @@ -225,6 +312,7 @@ static int icmp6_router_advertisment_recv(sd_event_source *s, int fd,
>          int r, buflen;
>          ssize_t len;
>          _cleanup_free_ struct nd_router_advert *ra = NULL;
> +        _cleanup_icmp6_link_free_ struct icmp6_link *link = NULL;
>          int event = ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE;
>
>          assert(s);
> @@ -251,6 +339,17 @@ static int icmp6_router_advertisment_recv(sd_event_source *s, int fd,
>          if (ra->nd_ra_code != 0)
>                  return 0;
>
> +        if (!nd->link) {
> +                r = icmp6_link_new(&link);
> +                if (r < 0) {
> +                        log_icmp6_nd(nd, "Could not allocate ICMP6 link struct: %m");
> +                        return 0;
> +                }
> +
> +                nd->link = link;
> +                link = NULL;
> +        }
> +
>          nd->timeout = sd_event_source_unref(nd->timeout);
>
>          nd->state = ICMP6_ROUTER_ADVERTISMENT_LISTEN;
> --
> 2.1.4
>
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel


More information about the systemd-devel mailing list