Acked-by: Ethan Jackson <[email protected]>


On Tue, Jul 23, 2013 at 5:07 PM, Ben Pfaff <[email protected]> wrote:
> Signed-off-by: Ben Pfaff <[email protected]>
> ---
>  lib/dpif-linux.c |  154 ++++++++++++++++++++++++++---------------------------
>  1 files changed, 76 insertions(+), 78 deletions(-)
>
> diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
> index c972197..3935eff 100644
> --- a/lib/dpif-linux.c
> +++ b/lib/dpif-linux.c
> @@ -148,26 +148,26 @@ struct dpif_linux {
>      int event_offset;           /* Offset into 'epoll_events'. */
>
>      /* Change notification. */
> -    struct sset changed_ports;  /* Ports that have changed. */
> -    struct nln_notifier *port_notifier;
> -    bool change_error;
> +    struct nl_sock *port_notifier; /* vport multicast group subscriber. */
>  };
>
>  static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5);
>
> -/* Generic Netlink family numbers for OVS. */
> +/* Generic Netlink family numbers for OVS.
> + *
> + * Initialized by dpif_linux_init(). */
>  static int ovs_datapath_family;
>  static int ovs_vport_family;
>  static int ovs_flow_family;
>  static int ovs_packet_family;
>
> -/* Generic Netlink socket. */
> -static struct nln *nln = NULL;
> +/* Generic Netlink multicast groups for OVS.
> + *
> + * Initialized by dpif_linux_init(). */
> +static unsigned int ovs_vport_mcgroup;
>
>  static int dpif_linux_init(void);
> -static void open_dpif(const struct dpif_linux_dp *, struct dpif **);
> -static bool dpif_linux_nln_parse(struct ofpbuf *, void *);
> -static void dpif_linux_port_changed(const void *vport, void *dpif);
> +static int open_dpif(const struct dpif_linux_dp *, struct dpif **);
>  static uint32_t dpif_linux_port_get_pid(const struct dpif *,
>                                          odp_port_t port_no);
>
> @@ -235,27 +235,27 @@ dpif_linux_open(const struct dpif_class *class 
> OVS_UNUSED, const char *name,
>          return error;
>      }
>
> -    open_dpif(&dp, dpifp);
> +    error = open_dpif(&dp, dpifp);
>      ofpbuf_delete(buf);
> -    return 0;
> +    return error;
>  }
>
> -static void
> +static int
>  open_dpif(const struct dpif_linux_dp *dp, struct dpif **dpifp)
>  {
>      struct dpif_linux *dpif;
>
>      dpif = xzalloc(sizeof *dpif);
> -    dpif->port_notifier = nln_notifier_create(nln, dpif_linux_port_changed,
> -                                              dpif);
> +    dpif->port_notifier = NULL;
>      dpif->epoll_fd = -1;
>
>      dpif_init(&dpif->dpif, &dpif_linux_class, dp->name,
>                dp->dp_ifindex, dp->dp_ifindex);
>
>      dpif->dp_ifindex = dp->dp_ifindex;
> -    sset_init(&dpif->changed_ports);
>      *dpifp = &dpif->dpif;
> +
> +    return 0;
>  }
>
>  static void
> @@ -374,9 +374,8 @@ dpif_linux_close(struct dpif *dpif_)
>  {
>      struct dpif_linux *dpif = dpif_linux_cast(dpif_);
>
> -    nln_notifier_destroy(dpif->port_notifier);
> +    nl_sock_destroy(dpif->port_notifier);
>      destroy_channels(dpif);
> -    sset_destroy(&dpif->changed_ports);
>      free(dpif);
>  }
>
> @@ -392,22 +391,6 @@ dpif_linux_destroy(struct dpif *dpif_)
>      return dpif_linux_dp_transact(&dp, NULL, NULL);
>  }
>
> -static void
> -dpif_linux_run(struct dpif *dpif_ OVS_UNUSED)
> -{
> -    if (nln) {
> -        nln_run(nln);
> -    }
> -}
> -
> -static void
> -dpif_linux_wait(struct dpif *dpif OVS_UNUSED)
> -{
> -    if (nln) {
> -        nln_wait(nln);
> -    }
> -}
> -
>  static int
>  dpif_linux_get_stats(const struct dpif *dpif_, struct dpif_dp_stats *stats)
>  {
> @@ -736,15 +719,61 @@ dpif_linux_port_poll(const struct dpif *dpif_, char 
> **devnamep)
>  {
>      struct dpif_linux *dpif = dpif_linux_cast(dpif_);
>
> -    if (dpif->change_error) {
> -        dpif->change_error = false;
> -        sset_clear(&dpif->changed_ports);
> +    /* Lazily create the Netlink socket to listen for notifications. */
> +    if (!dpif->port_notifier) {
> +        struct nl_sock *sock;
> +        int error;
> +
> +        error = nl_sock_create(NETLINK_GENERIC, &sock);
> +        if (error) {
> +            return error;
> +        }
> +
> +        error = nl_sock_join_mcgroup(sock, ovs_vport_mcgroup);
> +        if (error) {
> +            nl_sock_destroy(sock);
> +            return error;
> +        }
> +        dpif->port_notifier = sock;
> +
> +        /* We have no idea of the current state so report that everything
> +         * changed. */
> +        return ENOBUFS;
> +    }
> +
> +    for (;;) {
> +        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> +        uint64_t buf_stub[4096 / 8];
> +        struct ofpbuf buf;
> +        int error;
> +
> +        ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub);
> +        error = nl_sock_recv(dpif->port_notifier, &buf, false);
> +        if (!error) {
> +            struct dpif_linux_vport vport;
> +
> +            error = dpif_linux_vport_from_ofpbuf(&vport, &buf);
> +            if (!error) {
> +                if (vport.dp_ifindex == dpif->dp_ifindex
> +                    && (vport.cmd == OVS_VPORT_CMD_NEW
> +                        || vport.cmd == OVS_VPORT_CMD_DEL
> +                        || vport.cmd == OVS_VPORT_CMD_SET)) {
> +                    VLOG_DBG("port_changed: dpif:%s vport:%s cmd:%"PRIu8,
> +                             dpif->dpif.full_name, vport.name, vport.cmd);
> +                    *devnamep = xstrdup(vport.name);
> +                    return 0;
> +                } else {
> +                    continue;
> +                }
> +            }
> +        } else if (error == EAGAIN) {
> +            return EAGAIN;
> +        }
> +
> +        VLOG_WARN_RL(&rl, "error reading or parsing netlink (%s)",
> +                     ovs_strerror(error));
> +        nl_sock_drain(dpif->port_notifier);
>          return ENOBUFS;
> -    } else if (!sset_is_empty(&dpif->changed_ports)) {
> -        *devnamep = sset_pop(&dpif->changed_ports);
> -        return 0;
> -    } else {
> -        return EAGAIN;
>      }
>  }
>
> @@ -752,7 +781,10 @@ static void
>  dpif_linux_port_poll_wait(const struct dpif *dpif_)
>  {
>      const struct dpif_linux *dpif = dpif_linux_cast(dpif_);
> -    if (!sset_is_empty(&dpif->changed_ports) || dpif->change_error) {
> +
> +    if (dpif->port_notifier) {
> +        nl_sock_wait(dpif->port_notifier, POLLIN);
> +    } else {
>          poll_immediate_wake();
>      }
>  }
> @@ -1407,8 +1439,8 @@ const struct dpif_class dpif_linux_class = {
>      dpif_linux_open,
>      dpif_linux_close,
>      dpif_linux_destroy,
> -    dpif_linux_run,
> -    dpif_linux_wait,
> +    NULL,                       /* run */
> +    NULL,                       /* wait */
>      dpif_linux_get_stats,
>      dpif_linux_port_add,
>      dpif_linux_port_del,
> @@ -1444,8 +1476,6 @@ dpif_linux_init(void)
>      static int error;
>
>      if (ovsthread_once_start(&once)) {
> -        unsigned int ovs_vport_mcgroup;
> -
>          error = nl_lookup_genl_family(OVS_DATAPATH_FAMILY,
>                                        &ovs_datapath_family);
>          if (error) {
> @@ -1468,11 +1498,6 @@ dpif_linux_init(void)
>                                             &ovs_vport_mcgroup,
>                                             OVS_VPORT_MCGROUP_FALLBACK_ID);
>          }
> -        if (!error) {
> -            static struct dpif_linux_vport vport;
> -            nln = nln_create(NETLINK_GENERIC, ovs_vport_mcgroup,
> -                             dpif_linux_nln_parse, &vport);
> -        }
>
>          ovsthread_once_done(&once);
>      }
> @@ -1497,33 +1522,6 @@ dpif_linux_is_internal_device(const char *name)
>
>      return reply.type == OVS_VPORT_TYPE_INTERNAL;
>  }
> -
> -static bool
> -dpif_linux_nln_parse(struct ofpbuf *buf, void *vport_)
> -{
> -    struct dpif_linux_vport *vport = vport_;
> -    return dpif_linux_vport_from_ofpbuf(vport, buf) == 0;
> -}
> -
> -static void
> -dpif_linux_port_changed(const void *vport_, void *dpif_)
> -{
> -    const struct dpif_linux_vport *vport = vport_;
> -    struct dpif_linux *dpif = dpif_;
> -
> -    if (vport) {
> -        if (vport->dp_ifindex == dpif->dp_ifindex
> -            && (vport->cmd == OVS_VPORT_CMD_NEW
> -                || vport->cmd == OVS_VPORT_CMD_DEL
> -                || vport->cmd == OVS_VPORT_CMD_SET)) {
> -            VLOG_DBG("port_changed: dpif:%s vport:%s cmd:%"PRIu8,
> -                     dpif->dpif.full_name, vport->name, vport->cmd);
> -            sset_add(&dpif->changed_ports, vport->name);
> -        }
> -    } else {
> -        dpif->change_error = true;
> -    }
> -}
>
>  /* Parses the contents of 'buf', which contains a "struct ovs_header" 
> followed
>   * by Netlink attributes, into 'vport'.  Returns 0 if successful, otherwise a
> --
> 1.7.2.5
>
> _______________________________________________
> dev mailing list
> [email protected]
> http://openvswitch.org/mailman/listinfo/dev
X-CudaMail-Whitelist-To: [email protected]
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to