[systemd-devel] [PATCH] sd-dhcp: implement IPv4 link-local support

Umut Tezduyar Lindskog umut.tezduyar at axis.com
Fri Feb 28 00:17:34 PST 2014


Hi,

> -----Original Message-----
> From: Zbigniew Jędrzejewski-Szmek [mailto:zbyszek at in.waw.pl]
> Sent: den 28 februari 2014 04:08
> To: Umut Tezduyar Lindskog
> Cc: systemd-devel at lists.freedesktop.org; Umut Tezduyar Lindskog
> Subject: Re: [systemd-devel] [PATCH] sd-dhcp: implement IPv4 link-local
> support
> 
> On Thu, Feb 27, 2014 at 09:54:17PM +0100, Umut Tezduyar Lindskog wrote:
> > Implements IPv4LL with respect to RFC 3927
> > (http://tools.ietf.org/rfc/rfc3927.txt) and integrates it with
> > networkd. Majority of the IPv4LL state machine is taken from avahi
> > (http://avahi.org/) project's autoip.
> >
> > IPv4LL can be enabled by IPv4LL=yes under [Network] section of
> > .network file.
> >
> > IPv4LL works independent of DHCP but if DHCP lease is aquired, then LL
> > address will be dropped.
> Looks good.
> 
> Minor thoughts below:
> 
> > +#define log_ipv4ll(ll, fmt, ...) log_meta(LOG_DEBUG, __FILE__,
> > +__LINE__, __func__, "IPv4LL: " fmt, ##__VA_ARGS__)
> 
> I imagine that a user might want to control the log level of various
> subsystems independently. It's nice that this is already a macro:
> at some point we might want to turn the level into something configurable
> on its own.
> 
> > +        ipv4ll_set_state (ll, IPV4LL_STATE_INIT, 1);
> Indentation.
> 
> > +        if (ll->address) {
> > +                do {
> > +                        uint32_t r = random_u32() & 0x0000FFFF;
> > +                        addr = htonl(IPV4LL_NETWORK | r);
> > +                } while (addr == ll->address || !(
> > +                        ((ntohl(addr) & IPV4LL_NETMASK) == IPV4LL_NETWORK) &&
> > +                        ((ntohl(addr) & 0x0000FF00) != 0x0000) &&
> > +                        ((ntohl(addr) & 0x0000FF00) != 0xFF00)));
> Maybe one of the negations can be inverted:
> 
>                 } while (addr == ll->address ||
>                          (ntohl(addr) & IPV4LL_NETMASK) != IPV4LL_NETWORK ||
>                          (ntohl(addr) & 0x0000FF00) == 0x0000 ||
>                          (ntohl(addr) & 0x0000FF00) == 0xFF00);
> 
> This seems more readable without all those parantheses.

I agree.

> 
> 
> > +                if (ll->state == IPV4LL_STATE_ANNOUNCING ||
> > +                    ll->state == IPV4LL_STATE_RUNNING) {
> IN_SET(ll->state, IPV4LL_STATE_ANNOUNCING, IPV4LL_STATE_RUNNING)
> 
> > +
> > +                        if (ipv4ll_arp_conflict(ll, in_packet)) {
> > +
> > +                                r = sd_event_get_now_monotonic(ll->event,
> &time_now);
> > +                                if (r < 0)
> > +                                        goto out;
> > +
> > +                                /* Defend address */
> > +                                if (time_now > ll->defend_window) {
> > +                                        ll->defend_window = time_now + DEFEND_INTERVAL
> * USEC_PER_SEC;
> > +                                        arp_packet_announcement(&out_packet, ll->address,
> &ll->mac_addr);
> > +                                        out_packet_ready = 1;
> > +                                } else
> > +                                        conflicted = 1;
> > +                        }
> > +
> > +                } else if (ll->state == IPV4LL_STATE_WAITING_PROBE ||
> > +                           ll->state == IPV4LL_STATE_PROBING ||
> > +                           ll->state ==
> > + IPV4LL_STATE_WAITING_ANNOUNCE) {
> IN_SET...

Sorry, didn't understand it. What is this?

> 
> > +
> > +                        conflicted = ipv4ll_arp_probe_conflict(ll, in_packet);
> > +                }
> > +
> > +                if (conflicted) {
> > +                        log_ipv4ll(ll, "CONFLICT");
> Could we log more information here... With this we'd just have "IPv4LL:
> CONFLICT"
> in the logs. It would be nice to at least see the details of the conflicting
> address of something.

It is actually just a conflict. Meaning you will drop your previously ANNOUNCED address. And after CONFLICT, you will see PROBE & ANNOUNCE with new picked address. But maybe it is best to write down the conflicting address in case logs were rotated many many times. Either way for me.

> 
> > +                        r = ipv4ll_client_notify(ll, IPV4LL_EVENT_CONFLICT);
> > +                        ll->claimed_address = 0;
> > +
> > +                        /* Pick a new address */
> > +                        ll->address = ipv4ll_pick_address(ll);
> > +                        ll->conflict++;
> > +                        ll->defend_window = 0;
> > +                        ipv4ll_set_state(ll,
> > + IPV4LL_STATE_WAITING_PROBE, 1);
> > +
> > +                        if (ll->conflict >= MAX_CONFLICTS) {
> > +                                log_ipv4ll (ll, "MAX_CONFLICTS");
> Whitespace.

Thanks

> 
> 
> > +int sd_ipv4ll_start (sd_ipv4ll *ll) {
> > +        int r;
> > +
> > +        assert_return(ll, -EINVAL);
> > +        assert_return(ll->event, -EINVAL);
> > +        assert_return(ll->index > 0, -EINVAL);
> > +        assert_return(ll->state == IPV4LL_STATE_INIT, -EBUSY);
> > +
> > +        r = arp_network_bind_raw_socket(ll->index, &ll->link);
> > +
> > +        if (r < 0)
> > +                goto error;
> > +
> > +        ll->fd = r;
> > +        ll->conflict = 0;
> > +        ll->defend_window = 0;
> > +        ll->claimed_address = 0;
> > +
> > +        if (ll->address == 0)
> > +                ll->address = ipv4ll_pick_address(ll);
> > +
> > +        ipv4ll_set_state (ll, IPV4LL_STATE_INIT, 1);
> > +
> > +        r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd,
> > +                            EPOLLIN, ipv4ll_receive_message, ll);
> > +        if (r < 0)
> > +                goto error;
> > +
> > +        r = sd_event_source_set_priority(ll->receive_message, ll-
> >event_priority);
> > +        if (r < 0)
> > +                goto error;
> > +
> > +        r = sd_event_add_monotonic(ll->event, &ll->timer,
> now(CLOCK_MONOTONIC), 0,
> > +                                   ipv4ll_timer, ll);
> > +
> > +        if (r < 0)
> > +                goto error;
> > +
> > +        r = sd_event_source_set_priority(ll->timer,
> > + ll->event_priority);
> > +
> > +error:
> > +        if (r < 0)
> > +                ipv4ll_stop(ll, IPV4LL_EVENT_STOP);
> Please not 'error', if the return value might actually be successful.

Makes sense.

> 
> > +        return 0;
> > +}
> > +
> > +int sd_ipv4ll_stop(sd_ipv4ll *ll) {
> > +        return ipv4ll_stop(ll, IPV4LL_EVENT_STOP); }
> > +
> > +void sd_ipv4ll_free (sd_ipv4ll *ll) {
> > +        if (!ll)
> > +                return;
> > +
> > +        sd_ipv4ll_stop(ll);
> > +        sd_ipv4ll_detach_event(ll);
> > +
> > +        free(ll);
> > +}
> > +
> > +DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4ll*, sd_ipv4ll_free); #define
> > +_cleanup_ipv4ll_free_ _cleanup_(sd_ipv4ll_freep)
> Defs at the top...

It doesn't matter for me but we should do it all same everywhere I guess. Last time I checked, DHCP was doing it this way.

> 
> >
> > -        if (!link->network->static_routes && !link->dhcp_lease)
> > +        if (!link->network->static_routes && !link->dhcp_lease &&
> > +                (!link->ipv4ll || sd_ipv4ll_get_address(link->ipv4ll,
> > + &a) < 0))
> >                  return link_enter_configured(link);
> 
> Hm, sd_ipv4ll_get_address() < 0 and link_enter_configured()? This is
> confusing.
> 
> >  static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void
> > *userdata, sd_bus_error *ret_error) { @@ -493,7 +592,7 @@ static int
> dhcp_lease_lost(Link *link) {
> >                  address->in_addr.in = addr;
> >                  address->prefixlen = prefixlen;
> >
> > -                address_drop(address, link, address_drop_handler);
> > +                address_drop(address, link, &address_drop_handler);
> I don't think this adds clarity... And we don't actually use & with functions
> anywhere.

Again, it doesn't matter for me but we should stick to same. In DHCP code, it was mixed usage. I have converted them too to use reference. 

> 
> > +                        if (link->ipv4ll) {
> > +                                r = sd_ipv4ll_stop (link->ipv4ll);
> Whitespace.
Thanks.
> 
> > +        log_struct_link(LOG_INFO, link,
> > +                "MESSAGE=%s: IPv4 link-local address %u.%u.%u.%u",
> > +                 link->ifname,
> > +                 ADDRESS_FMT_VAL(address),
> > +                 NULL);
> Indentation.
> 
> Zbyszek

Thanks for doing code review
Umut


More information about the systemd-devel mailing list