[LEDE-DEV] [PATCH odhcpd v2] Support muliple RAs on single interface

Pierre Pfister (ppfister) ppfister at cisco.com
Thu Jan 4 04:42:53 PST 2018


Hello Hans,

Thanks for committing !
In the multi-homing case, you would typically have two RAs on the same interface with one PIO per RA.
Therefore you would define two software interfaces, each with a prefix-filter option making sure a single prefix is included in each RA.
So I think it would work in the cases I can imagine today. Maybe other use-cases may require some change in the future.

Thanks,

- Pierre

> Le 4 janv. 2018 à 13:33, Hans Dedecker <dedeckeh at gmail.com> a écrit :
> 
> On Thu, Jan 4, 2018 at 11:12 AM, Pierre Pfister (ppfister)
> <ppfister at cisco.com> wrote:
>> Hello Hans and happy new year !
>> 
>> As requested in your comment to v1, I have updated the README file.
>> Would you mind reviewing this new version of the patch ?
>> 
>> Thanks,
>> 
>> - Pierre
> Hi Pierre,
> 
> Also a happy new year!
> I've reviewed the patch and it was committed in
> https://git.lede-project.org/?p=project/odhcpd.git;a=commit;h=750e457e3000187b85906814a2529ede24775325.
> As the prefix-filter parameter allows to specify only one prefix for a
> given logical interface; I'm wondering is this flexible enough for the
> multihoming use-case ?
> 
> Hans
>> 
>>> Le 8 déc. 2017 à 15:15, ppfister at cisco.com a écrit :
>>> 
>>> From: Pierre Pfister <ppfister at cisco.com>
>>> 
>>> IETF is moving toward implementing IPv6 multihoming by sending
>>> multiple RAs on a single interface:
>>> - draft-ietf-intarea-provisioning-domains-00
>>> - draft-ietf-rtgwg-enterprise-pa-multihoming-02
>>> 
>>> odhcpd supports configuration of multiple software interfaces
>>> on the same physical interface, which already advertises
>>> multiple RAs, but had two issues:
>>> - Each RA includes all the prefixes available on the interface.
>>> - Replies to sollicits with a single RA.
>>> 
>>> This patch introduces the prefix_filter configuration parameter
>>> which allows filtering prefixes that are sent in a given RA,
>>> and fixes the sollicit code in order to reply with all the RAs
>>> that are configured on a given interface.
>>> 
>>> Signed-off-by: Pierre Pfister <ppfister at cisco.com>
>>> ---
>>> README       |  3 +++
>>> src/config.c | 19 +++++++++++++++++++
>>> src/odhcpd.c | 28 +++++++++++++++++++---------
>>> src/odhcpd.h |  2 ++
>>> src/router.c |  5 +++++
>>> 5 files changed, 48 insertions(+), 9 deletions(-)
>>> 
>>> diff --git a/README b/README
>>> index 95f59bf..0c562e6 100644
>>> --- a/README
>>> +++ b/README
>>> @@ -134,6 +134,9 @@ ra_mtu                    integer 0                       MTU to be advertised in
>>>                                                      RA messages
>>> ndproxy_routing               bool    1                       Learn routes from NDP
>>> ndproxy_slave         bool    0                       NDProxy external slave
>>> +prefix_filter                string  ::/0                    Only advertise on-link prefixes within
>>> +                     [IPv6 prefix]                   the provided IPv6 prefix; others are
>>> +                                                     filtered out.
>>> 
>>> 
>>> Sections of type host (static leases)
>>> diff --git a/src/config.c b/src/config.c
>>> index bb885d0..409b3b8 100644
>>> --- a/src/config.c
>>> +++ b/src/config.c
>>> @@ -62,6 +62,7 @@ enum {
>>>      IFACE_ATTR_PD_CER,
>>>      IFACE_ATTR_NDPROXY_ROUTING,
>>>      IFACE_ATTR_NDPROXY_SLAVE,
>>> +     IFACE_ATTR_PREFIX_FILTER,
>>>      IFACE_ATTR_MAX
>>> };
>>> 
>>> @@ -104,6 +105,7 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
>>>      [IFACE_ATTR_RA_MTU] = { .name = "ra_mtu", .type = BLOBMSG_TYPE_INT32 },
>>>      [IFACE_ATTR_NDPROXY_ROUTING] = { .name = "ndproxy_routing", .type = BLOBMSG_TYPE_BOOL },
>>>      [IFACE_ATTR_NDPROXY_SLAVE] = { .name = "ndproxy_slave", .type = BLOBMSG_TYPE_BOOL },
>>> +     [IFACE_ATTR_PREFIX_FILTER] = { .name = "prefix_filter", .type = BLOBMSG_TYPE_STRING },
>>> };
>>> 
>>> static const struct uci_blob_param_info iface_attr_info[IFACE_ATTR_MAX] = {
>>> @@ -720,6 +722,23 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr
>>>      if ((c = tb[IFACE_ATTR_NDPROXY_SLAVE]))
>>>              iface->external = blobmsg_get_bool(c);
>>> 
>>> +     if ((c = tb[IFACE_ATTR_PREFIX_FILTER])) {
>>> +             const char *str = blobmsg_get_string(c);
>>> +             char *astr = malloc(strlen(str) + 1);
>>> +             char *delim;
>>> +             int l;
>>> +             if (!astr || !strcpy(astr, str) ||
>>> +                             (delim = strchr(astr, '/')) == NULL || (*(delim++) = 0) ||
>>> +                             sscanf(delim, "%i", &l) == 0 || l > 128 ||
>>> +                             inet_pton(AF_INET6, astr, &iface->pio_filter_addr) == 0) {
>>> +                     iface->pio_filter_length = 0;
>>> +             } else {
>>> +                     iface->pio_filter_length = l;
>>> +             }
>>> +             if (astr)
>>> +                     free(astr);
>>> +     }
>>> +
>>>      return 0;
>>> 
>>> err:
>>> diff --git a/src/odhcpd.c b/src/odhcpd.c
>>> index 97a6de9..58c4338 100644
>>> --- a/src/odhcpd.c
>>> +++ b/src/odhcpd.c
>>> @@ -371,12 +371,6 @@ static void odhcpd_receive_packets(struct uloop_fd *u, _unused unsigned int even
>>>              if (addr.ll.sll_family == AF_PACKET)
>>>                      destiface = addr.ll.sll_ifindex;
>>> 
>>> -             struct interface *iface =
>>> -                             odhcpd_get_interface_by_index(destiface);
>>> -
>>> -             if (!iface && addr.nl.nl_family != AF_NETLINK)
>>> -                     continue;
>>> -
>>>              char ipbuf[INET6_ADDRSTRLEN] = "kernel";
>>>              if (addr.ll.sll_family == AF_PACKET &&
>>>                              len >= (ssize_t)sizeof(struct ip6_hdr))
>>> @@ -386,10 +380,26 @@ static void odhcpd_receive_packets(struct uloop_fd *u, _unused unsigned int even
>>>              else if (addr.in.sin_family == AF_INET)
>>>                      inet_ntop(AF_INET, &addr.in.sin_addr, ipbuf, sizeof(ipbuf));
>>> 
>>> -             syslog(LOG_DEBUG, "Received %li Bytes from %s%%%s", (long)len,
>>> -                             ipbuf, (iface) ? iface->ifname : "netlink");
>>> +             // From netlink
>>> +             if (addr.nl.nl_family == AF_NETLINK) {
>>> +                     syslog(LOG_DEBUG, "Received %li Bytes from %s%%%s", (long)len,
>>> +                                     ipbuf, "netlink");
>>> +                     e->handle_dgram(&addr, data_buf, len, NULL, dest);
>>> +                     return;
>>> +             } else if (destiface != 0) {
>>> +                     struct interface *iface;
>>> +                     list_for_each_entry(iface, &interfaces, head) {
>>> +                             if (iface->ifindex != destiface)
>>> +                                     continue;
>>> +
>>> +                             syslog(LOG_DEBUG, "Received %li Bytes from %s%%%s", (long)len,
>>> +                                             ipbuf, iface->ifname);
>>> +
>>> +                             e->handle_dgram(&addr, data_buf, len, iface, dest);
>>> +                     }
>>> +             }
>>> +
>>> 
>>> -             e->handle_dgram(&addr, data_buf, len, iface, dest);
>>>      }
>>> }
>>> 
>>> diff --git a/src/odhcpd.h b/src/odhcpd.h
>>> index fbfeb67..48ee51e 100644
>>> --- a/src/odhcpd.h
>>> +++ b/src/odhcpd.h
>>> @@ -208,6 +208,8 @@ struct interface {
>>>      bool ra_advrouter;
>>>      bool ra_useleasetime;
>>>      bool no_dynamic_dhcp;
>>> +     uint8_t pio_filter_length;
>>> +     struct in6_addr pio_filter_addr;
>>> 
>>>      // RA
>>>      int learn_routes;
>>> diff --git a/src/router.c b/src/router.c
>>> index c35cd12..7bc94ed 100644
>>> --- a/src/router.c
>>> +++ b/src/router.c
>>> @@ -380,6 +380,11 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add
>>>                      continue;
>>>              }
>>> 
>>> +             if (odhcpd_bmemcmp(&addr->addr, &iface->pio_filter_addr,
>>> +                             iface->pio_filter_length) != 0 ||
>>> +                             addr->prefix < iface->pio_filter_length)
>>> +                     continue; // PIO filtered out of this RA
>>> +
>>>              struct nd_opt_prefix_info *p = NULL;
>>>              for (size_t i = 0; i < pfxs_cnt; ++i) {
>>>                      if (addr->prefix == pfxs[i].nd_opt_pi_prefix_len &&
>>> --
>>> 2.13.6 (Apple Git-96)
>>> 
>>> 
>>> _______________________________________________
>>> Lede-dev mailing list
>>> Lede-dev at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/lede-dev
>> 



More information about the Lede-dev mailing list