Thanks for the reviews.  I pushed this to master, branch-1.4, branch-1.5.

On Tue, Jan 31, 2012 at 06:16:54PM -0800, Ethan Jackson wrote:
> May as well set the minInteger in the documentation to 15.  Otherwise
> looks good.
> 
> Ethan
> 
> On Tue, Jan 24, 2012 at 13:44, Ben Pfaff <b...@nicira.com> wrote:
> > NICS-11.
> > Signed-off-by: Ben Pfaff <b...@nicira.com>
> > ---
> >  NEWS                       |    2 ++
> >  lib/learning-switch.c      |    6 ++++--
> >  lib/mac-learning.c         |   41 ++++++++++++++++++++++++++++++++++-------
> >  lib/mac-learning.h         |   10 +++++++---
> >  ofproto/ofproto-dpif.c     |   13 +++++++++++--
> >  ofproto/ofproto-provider.h |    6 +++++-
> >  ofproto/ofproto.c          |   10 ++++++++++
> >  ofproto/ofproto.h          |    3 ++-
> >  vswitchd/bridge.c          |   17 +++++++++++++++++
> >  vswitchd/vswitch.xml       |   20 ++++++++++++++++++++
> >  10 files changed, 112 insertions(+), 16 deletions(-)
> >
> > diff --git a/NEWS b/NEWS
> > index d7332f8..14753f1 100644
> > --- a/NEWS
> > +++ b/NEWS
> > @@ -31,6 +31,8 @@ v1.4.0 - xx xxx xxxx
> >       broken device drivers are no longer in widespread use, we will
> >       delete this feature.)  See ovs-vswitchd.conf.db(5) for more
> >       information.
> > +    - The default MAC learning timeout has been increased from 60 seconds
> > +      to 300 seconds.  The MAC learning timeout is now configurable.
> >     - OpenFlow:
> >        - Added ability to match on IPv6 flow label through NXM.
> >        - Added ability to match on ECN bits in IPv4 and IPv6 through NXM.
> > diff --git a/lib/learning-switch.c b/lib/learning-switch.c
> > index 3bcb961..60cf731 100644
> > --- a/lib/learning-switch.c
> > +++ b/lib/learning-switch.c
> > @@ -1,5 +1,5 @@
> >  /*
> > - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
> > + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
> >  *
> >  * Licensed under the Apache License, Version 2.0 (the "License");
> >  * you may not use this file except in compliance with the License.
> > @@ -97,7 +97,9 @@ lswitch_create(struct rconn *rconn, const struct 
> > lswitch_config *cfg)
> >     sw->max_idle = cfg->max_idle;
> >     sw->datapath_id = 0;
> >     sw->last_features_request = time_now() - 1;
> > -    sw->ml = cfg->mode == LSW_LEARN ? mac_learning_create() : NULL;
> > +    sw->ml = (cfg->mode == LSW_LEARN
> > +              ? mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME)
> > +              : NULL);
> >     sw->action_normal = cfg->mode == LSW_NORMAL;
> >
> >     flow_wildcards_init_exact(&sw->wc);
> > diff --git a/lib/mac-learning.c b/lib/mac-learning.c
> > index efd1dd4..836bcd4 100644
> > --- a/lib/mac-learning.c
> > +++ b/lib/mac-learning.c
> > @@ -1,5 +1,5 @@
> >  /*
> > - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
> > + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
> >  *
> >  * Licensed under the Apache License, Version 2.0 (the "License");
> >  * you may not use this file except in compliance with the License.
> > @@ -37,12 +37,12 @@ VLOG_DEFINE_THIS_MODULE(mac_learning);
> >  COVERAGE_DEFINE(mac_learning_learned);
> >  COVERAGE_DEFINE(mac_learning_expired);
> >
> > -/* Returns the number of seconds since 'e' was last learned. */
> > +/* Returns the number of seconds since 'e' (within 'ml') was last learned. 
> > */
> >  int
> > -mac_entry_age(const struct mac_entry *e)
> > +mac_entry_age(const struct mac_learning *ml, const struct mac_entry *e)
> >  {
> >     time_t remaining = e->expires - time_now();
> > -    return MAC_ENTRY_IDLE_TIME - remaining;
> > +    return ml->idle_time - remaining;
> >  }
> >
> >  static uint32_t
> > @@ -98,9 +98,18 @@ get_lru(struct mac_learning *ml, struct mac_entry **e)
> >     }
> >  }
> >
> > -/* Creates and returns a new MAC learning table. */
> > +static unsigned int
> > +normalize_idle_time(unsigned int idle_time)
> > +{
> > +    return (idle_time < 15 ? 15
> > +            : idle_time > 3600 ? 3600
> > +            : idle_time);
> > +}
> > +
> > +/* Creates and returns a new MAC learning table with an initial MAC aging
> > + * timeout of 'idle_time' seconds. */
> >  struct mac_learning *
> > -mac_learning_create(void)
> > +mac_learning_create(unsigned int idle_time)
> >  {
> >     struct mac_learning *ml;
> >
> > @@ -109,6 +118,7 @@ mac_learning_create(void)
> >     hmap_init(&ml->table);
> >     ml->secret = random_uint32();
> >     ml->flood_vlans = NULL;
> > +    ml->idle_time = normalize_idle_time(idle_time);
> >     return ml;
> >  }
> >
> > @@ -146,6 +156,23 @@ mac_learning_set_flood_vlans(struct mac_learning *ml,
> >     }
> >  }
> >
> > +/* Changes the MAC aging timeout of 'ml' to 'idle_time' seconds. */
> > +void
> > +mac_learning_set_idle_time(struct mac_learning *ml, unsigned int idle_time)
> > +{
> > +    idle_time = normalize_idle_time(idle_time);
> > +    if (idle_time != ml->idle_time) {
> > +        struct mac_entry *e;
> > +        int delta;
> > +
> > +        delta = (int) idle_time - (int) ml->idle_time;
> > +        LIST_FOR_EACH (e, lru_node, &ml->lrus) {
> > +            e->expires += delta;
> > +        }
> > +        ml->idle_time = idle_time;
> > +    }
> > +}
> > +
> >  static bool
> >  is_learning_vlan(const struct mac_learning *ml, uint16_t vlan)
> >  {
> > @@ -199,7 +226,7 @@ mac_learning_insert(struct mac_learning *ml,
> >
> >     /* Mark 'e' as recently used. */
> >     list_push_back(&ml->lrus, &e->lru_node);
> > -    e->expires = time_now() + MAC_ENTRY_IDLE_TIME;
> > +    e->expires = time_now() + ml->idle_time;
> >
> >     return e;
> >  }
> > diff --git a/lib/mac-learning.h b/lib/mac-learning.h
> > index 4bcf221..8d0ac62 100644
> > --- a/lib/mac-learning.h
> > +++ b/lib/mac-learning.h
> > @@ -24,10 +24,12 @@
> >  #include "tag.h"
> >  #include "timeval.h"
> >
> > +struct mac_learning;
> > +
> >  #define MAC_MAX 2048
> >
> >  /* Time, in seconds, before expiring a mac_entry due to inactivity. */
> > -#define MAC_ENTRY_IDLE_TIME 300
> > +#define MAC_ENTRY_DEFAULT_IDLE_TIME 300
> >
> >  /* Time, in seconds, to lock an entry updated by a gratuitous ARP to avoid
> >  * relearning based on a reflection from a bond slave. */
> > @@ -50,7 +52,7 @@ struct mac_entry {
> >     } port;
> >  };
> >
> > -int mac_entry_age(const struct mac_entry *);
> > +int mac_entry_age(const struct mac_learning *, const struct mac_entry *);
> >
> >  /* Returns true if mac_learning_insert() just created 'mac' and the caller 
> > has
> >  * not yet properly initialized it. */
> > @@ -80,10 +82,11 @@ struct mac_learning {
> >                                    front, most recently used at the back. */
> >     uint32_t secret;            /* Secret for randomizing hash table. */
> >     unsigned long *flood_vlans; /* Bitmap of learning disabled VLANs. */
> > +    unsigned int idle_time;     /* Max age before deleting an entry. */
> >  };
> >
> >  /* Basics. */
> > -struct mac_learning *mac_learning_create(void);
> > +struct mac_learning *mac_learning_create(unsigned int idle_time);
> >  void mac_learning_destroy(struct mac_learning *);
> >
> >  void mac_learning_run(struct mac_learning *, struct tag_set *);
> > @@ -92,6 +95,7 @@ void mac_learning_wait(struct mac_learning *);
> >  /* Configuration. */
> >  bool mac_learning_set_flood_vlans(struct mac_learning *,
> >                                   const unsigned long *bitmap);
> > +void mac_learning_set_idle_time(struct mac_learning *, unsigned int 
> > idle_time);
> >
> >  /* Learning. */
> >  bool mac_learning_may_learn(const struct mac_learning *,
> > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> > index 471ba64..e3edec0 100644
> > --- a/ofproto/ofproto-dpif.c
> > +++ b/ofproto/ofproto-dpif.c
> > @@ -649,7 +649,7 @@ construct(struct ofproto *ofproto_, int *n_tablesp)
> >     ofproto->sflow = NULL;
> >     ofproto->stp = NULL;
> >     hmap_init(&ofproto->bundles);
> > -    ofproto->ml = mac_learning_create();
> > +    ofproto->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME);
> >     for (i = 0; i < MAX_MIRRORS; i++) {
> >         ofproto->mirrors[i] = NULL;
> >     }
> > @@ -2147,6 +2147,13 @@ forward_bpdu_changed(struct ofproto *ofproto_)
> >     /* Revalidate cached flows whenever forward_bpdu option changes. */
> >     ofproto->need_revalidate = true;
> >  }
> > +
> > +static void
> > +set_mac_idle_time(struct ofproto *ofproto_, unsigned int idle_time)
> > +{
> > +    struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
> > +    mac_learning_set_idle_time(ofproto->ml, idle_time);
> > +}
> >
> >  /* Ports. */
> >
> > @@ -5847,7 +5854,8 @@ ofproto_unixctl_fdb_show(struct unixctl_conn *conn, 
> > int argc OVS_UNUSED,
> >         struct ofbundle *bundle = e->port.p;
> >         ds_put_format(&ds, "%5d  %4d  "ETH_ADDR_FMT"  %3d\n",
> >                       ofbundle_get_a_port(bundle)->odp_port,
> > -                      e->vlan, ETH_ADDR_ARGS(e->mac), mac_entry_age(e));
> > +                      e->vlan, ETH_ADDR_ARGS(e->mac),
> > +                      mac_entry_age(ofproto->ml, e));
> >     }
> >     unixctl_command_reply(conn, 200, ds_cstr(&ds));
> >     ds_destroy(&ds);
> > @@ -6336,5 +6344,6 @@ const struct ofproto_class ofproto_dpif_class = {
> >     set_flood_vlans,
> >     is_mirror_output_bundle,
> >     forward_bpdu_changed,
> > +    set_mac_idle_time,
> >     set_realdev,
> >  };
> > diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
> > index b995831..f1a7e9a 100644
> > --- a/ofproto/ofproto-provider.h
> > +++ b/ofproto/ofproto-provider.h
> > @@ -1,5 +1,5 @@
> >  /*
> > - * Copyright (c) 2009, 2010, 2011 Nicira Networks.
> > + * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
> >  *
> >  * Licensed under the Apache License, Version 2.0 (the "License");
> >  * you may not use this file except in compliance with the License.
> > @@ -1062,6 +1062,10 @@ struct ofproto_class {
> >      * will be invoked. */
> >     void (*forward_bpdu_changed)(struct ofproto *ofproto);
> >
> > +    /* Sets the MAC aging timeout for the OFPP_NORMAL action to 
> > 'idle_time',
> > +     * in seconds. */
> > +    void (*set_mac_idle_time)(struct ofproto *ofproto, unsigned int 
> > idle_time);
> > +
> >  /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
> >  *
> >  * This is deprecated.  It is only for compatibility with broken device 
> > drivers
> > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> > index 0504026..9913a57 100644
> > --- a/ofproto/ofproto.c
> > +++ b/ofproto/ofproto.c
> > @@ -447,6 +447,16 @@ ofproto_set_forward_bpdu(struct ofproto *ofproto, bool 
> > forward_bpdu)
> >     }
> >  }
> >
> > +/* Sets the MAC aging timeout for the OFPP_NORMAL action on 'ofproto' to
> > + * 'idle_time', in seconds. */
> > +void
> > +ofproto_set_mac_idle_time(struct ofproto *ofproto, unsigned idle_time)
> > +{
> > +    if (ofproto->ofproto_class->set_mac_idle_time) {
> > +        ofproto->ofproto_class->set_mac_idle_time(ofproto, idle_time);
> > +    }
> > +}
> > +
> >  void
> >  ofproto_set_desc(struct ofproto *p,
> >                  const char *mfr_desc, const char *hw_desc,
> > diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
> > index 2d47878..24efa15 100644
> > --- a/ofproto/ofproto.h
> > +++ b/ofproto/ofproto.h
> > @@ -1,5 +1,5 @@
> >  /*
> > - * Copyright (c) 2009, 2010, 2011 Nicira Networks.
> > + * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
> >  *
> >  * Licensed under the Apache License, Version 2.0 (the "License");
> >  * you may not use this file except in compliance with the License.
> > @@ -205,6 +205,7 @@ void ofproto_set_extra_in_band_remotes(struct ofproto *,
> >  void ofproto_set_in_band_queue(struct ofproto *, int queue_id);
> >  void ofproto_set_flow_eviction_threshold(struct ofproto *, unsigned 
> > threshold);
> >  void ofproto_set_forward_bpdu(struct ofproto *, bool forward_bpdu);
> > +void ofproto_set_mac_idle_time(struct ofproto *, unsigned idle_time);
> >  void ofproto_set_desc(struct ofproto *,
> >                       const char *mfr_desc, const char *hw_desc,
> >                       const char *sw_desc, const char *serial_desc,
> > diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
> > index c40bcb5..625b96e 100644
> > --- a/vswitchd/bridge.c
> > +++ b/vswitchd/bridge.c
> > @@ -32,6 +32,7 @@
> >  #include "jsonrpc.h"
> >  #include "lacp.h"
> >  #include "list.h"
> > +#include "mac-learning.h"
> >  #include "netdev.h"
> >  #include "ofp-print.h"
> >  #include "ofpbuf.h"
> > @@ -156,6 +157,7 @@ static void bridge_configure_datapath_id(struct bridge 
> > *);
> >  static void bridge_configure_flow_eviction_threshold(struct bridge *);
> >  static void bridge_configure_netflow(struct bridge *);
> >  static void bridge_configure_forward_bpdu(struct bridge *);
> > +static void bridge_configure_mac_idle_time(struct bridge *);
> >  static void bridge_configure_sflow(struct bridge *, int 
> > *sflow_bridge_number);
> >  static void bridge_configure_stp(struct bridge *);
> >  static void bridge_configure_remotes(struct bridge *,
> > @@ -465,6 +467,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch 
> > *ovs_cfg)
> >         bridge_configure_mirrors(br);
> >         bridge_configure_flow_eviction_threshold(br);
> >         bridge_configure_forward_bpdu(br);
> > +        bridge_configure_mac_idle_time(br);
> >         bridge_configure_remotes(br, managers, n_managers);
> >         bridge_configure_netflow(br);
> >         bridge_configure_sflow(br, &sflow_bridge_number);
> > @@ -1271,6 +1274,20 @@ bridge_configure_forward_bpdu(struct bridge *br)
> >     ofproto_set_forward_bpdu(br->ofproto, forward_bpdu);
> >  }
> >
> > +/* Set MAC aging time for 'br'. */
> > +static void
> > +bridge_configure_mac_idle_time(struct bridge *br)
> > +{
> > +    const char *idle_time_str;
> > +    int idle_time;
> > +
> > +    idle_time_str = bridge_get_other_config(br->cfg, "mac-aging-time");
> > +    idle_time = (idle_time_str && atoi(idle_time_str)
> > +                 ? atoi(idle_time_str)
> > +                 : MAC_ENTRY_DEFAULT_IDLE_TIME);
> > +    ofproto_set_mac_idle_time(br->ofproto, idle_time);
> > +}
> > +
> >  static void
> >  bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
> >                           struct iface **hw_addr_iface)
> > diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
> > index 8c506e4..da5508e 100644
> > --- a/vswitchd/vswitch.xml
> > +++ b/vswitchd/vswitch.xml
> > @@ -553,6 +553,26 @@
> >         should be enabled.  Default is disabled, set to
> >         <code>true</code> to enable.
> >       </column>
> > +
> > +      <column name="other_config" key="mac-aging-time"
> > +              type='{"type": "integer", "minInteger": 1}'>
> > +        <p>
> > +          The maximum number of seconds to retain a MAC learning entry for
> > +          which no packets have been seen.  The default is currently 300
> > +          seconds (5 minutes).  The value, if specified, is forced into a
> > +          reasonable range, currently 15 to 3600 seconds.
> > +        </p>
> > +
> > +        <p>
> > +          A short MAC aging time allows a network to more quickly detect 
> > that a
> > +          host is no longer connected to a switch port.  However, it also 
> > makes
> > +          it more likely that packets will be flooded unnecessarily, when 
> > they
> > +          are addressed to a connected host that rarely transmits packets. 
> >  To
> > +          reduce the incidence of unnecessary flooding, use a MAC aging 
> > time
> > +          longer than the maximum interval at which a host will ordinarily
> > +          transmit packets.
> > +        </p>
> > +      </column>
> >     </group>
> >
> >     <group title="Bridge Status">
> > --
> > 1.7.2.5
> >
> > _______________________________________________
> > dev mailing list
> > dev@openvswitch.org
> > http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to