X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fnetdev-vport.c;h=b9c1bfe61ab28da77de889315f3e8ee5b83966bf;hb=12d685891c72d6009f0303edb94b3b6fabcd6228;hp=3067323671a1a7e87cd286214a385da56143c8f3;hpb=d84d4b88d26e3f37ce24f1d3eebe0d70ef264f73;p=openvswitch diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 30673236..b9c1bfe6 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -48,17 +48,12 @@ VLOG_DEFINE_THIS_MODULE(netdev_vport); -struct netdev_vport_notifier { - struct netdev_notifier notifier; - struct list list_node; - struct shash_node *shash_node; -}; - struct netdev_dev_vport { struct netdev_dev netdev_dev; struct ofpbuf *options; int dp_ifindex; /* -1 if unknown. */ uint32_t port_no; /* UINT32_MAX if unknown. */ + unsigned int change_seq; }; struct netdev_vport { @@ -73,11 +68,9 @@ struct vport_class { int (*unparse_config)(const char *name, const char *type, const struct nlattr *options, size_t options_len, struct shash *args); + bool (*config_equal)(const struct shash *nd_args, const struct shash *args); }; -static struct shash netdev_vport_notifiers = - SHASH_INITIALIZER(&netdev_vport_notifiers); - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); static int netdev_vport_create(const struct netdev_class *, const char *, @@ -242,6 +235,7 @@ netdev_vport_create(const struct netdev_class *netdev_class, const char *name, dev->options = options; dev->dp_ifindex = dp_ifindex; dev->port_no = port_no; + dev->change_seq = 1; *netdev_devp = &dev->netdev_dev; route_table_register(); @@ -322,6 +316,20 @@ netdev_vport_set_config(struct netdev_dev *dev_, const struct shash *args) return error; } +static bool +netdev_vport_config_equal(const struct netdev_dev *dev_, + const struct shash *args) +{ + const struct netdev_class *netdev_class = netdev_dev_get_class(dev_); + const struct vport_class *vport_class = vport_class_cast(netdev_class); + + if (vport_class->config_equal) { + return vport_class->config_equal(&dev_->args, args); + } else { + return smap_equal(&dev_->args, args); + } +} + static int netdev_vport_send(struct netdev *netdev, const void *data, size_t size) { @@ -485,57 +493,10 @@ netdev_vport_update_flags(struct netdev *netdev OVS_UNUSED, return 0; } -static char * -make_poll_name(const struct netdev *netdev) -{ - return xasprintf("%s:%s", netdev_get_type(netdev), netdev_get_name(netdev)); -} - -static int -netdev_vport_poll_add(struct netdev *netdev, - void (*cb)(struct netdev_notifier *), void *aux, - struct netdev_notifier **notifierp) -{ - char *poll_name = make_poll_name(netdev); - struct netdev_vport_notifier *notifier; - struct list *list; - struct shash_node *shash_node; - - shash_node = shash_find(&netdev_vport_notifiers, poll_name); - if (!shash_node) { - list = xmalloc(sizeof *list); - list_init(list); - shash_node = shash_add(&netdev_vport_notifiers, poll_name, list); - } else { - list = shash_node->data; - } - - notifier = xmalloc(sizeof *notifier); - netdev_notifier_init(¬ifier->notifier, netdev, cb, aux); - list_push_back(list, ¬ifier->list_node); - notifier->shash_node = shash_node; - - *notifierp = ¬ifier->notifier; - free(poll_name); - - return 0; -} - -static void -netdev_vport_poll_remove(struct netdev_notifier *notifier_) +static unsigned int +netdev_vport_change_seq(const struct netdev *netdev) { - struct netdev_vport_notifier *notifier = - CONTAINER_OF(notifier_, struct netdev_vport_notifier, notifier); - - struct list *list; - - list = list_remove(¬ifier->list_node); - if (list_is_empty(list)) { - shash_delete(&netdev_vport_notifiers, notifier->shash_node); - free(list); - } - - free(notifier); + return netdev_dev_vport_cast(netdev_get_dev(netdev))->change_seq; } static void @@ -578,20 +539,14 @@ netdev_vport_get_tnl_iface(const struct netdev *netdev) static void netdev_vport_poll_notify(const struct netdev *netdev) { - char *poll_name = make_poll_name(netdev); - struct list *list = shash_find_data(&netdev_vport_notifiers, - poll_name); + struct netdev_dev_vport *ndv; - if (list) { - struct netdev_vport_notifier *notifier; + ndv = netdev_dev_vport_cast(netdev_get_dev(netdev)); - LIST_FOR_EACH (notifier, list_node, list) { - struct netdev_notifier *n = ¬ifier->notifier; - n->cb(n); - } + ndv->change_seq++; + if (!ndv->change_seq) { + ndv->change_seq++; } - - free(poll_name); } /* Code specific to individual vport types. */ @@ -928,6 +883,44 @@ unparse_patch_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED, smap_add(args, "peer", nl_attr_get_string(a[ODP_PATCH_ATTR_PEER])); return 0; } + +/* Returns true if 'nd_args' is equivalent to 'args', otherwise false. + * Typically, 'nd_args' is the result of a call to unparse_tunnel_config() + * and 'args' is the original definition of the port. + * + * IPsec key configuration is handled by an external program, so it is not + * pushed down into the kernel module. Thus, when the "unparse_config" + * method is called on an existing IPsec-based vport, a simple + * comparison with the returned data will not match the original + * configuration. This function ignores configuration about keys when + * doing a comparison. + */ +static bool +config_equal_ipsec(const struct shash *nd_args, const struct shash *args) +{ + struct shash tmp1, tmp2; + bool result; + + smap_clone(&tmp1, nd_args); + smap_clone(&tmp2, args); + + shash_find_and_delete(&tmp1, "psk"); + shash_find_and_delete(&tmp2, "psk"); + shash_find_and_delete(&tmp1, "peer_cert"); + shash_find_and_delete(&tmp2, "peer_cert"); + shash_find_and_delete(&tmp1, "certificate"); + shash_find_and_delete(&tmp2, "certificate"); + shash_find_and_delete(&tmp1, "private_key"); + shash_find_and_delete(&tmp2, "private_key"); + shash_find_and_delete(&tmp1, "use_ssl_cert"); + shash_find_and_delete(&tmp2, "use_ssl_cert"); + + result = smap_equal(&tmp1, &tmp2); + smap_destroy(&tmp1); + smap_destroy(&tmp2); + + return result; +} #define VPORT_FUNCTIONS(GET_STATUS) \ NULL, \ @@ -937,6 +930,7 @@ unparse_patch_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED, netdev_vport_create, \ netdev_vport_destroy, \ netdev_vport_set_config, \ + netdev_vport_config_equal, \ \ netdev_vport_open, \ netdev_vport_close, \ @@ -985,8 +979,7 @@ unparse_patch_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED, \ netdev_vport_update_flags, \ \ - netdev_vport_poll_add, \ - netdev_vport_poll_remove, + netdev_vport_change_seq void netdev_vport_register(void) @@ -994,19 +987,19 @@ netdev_vport_register(void) static const struct vport_class vport_classes[] = { { ODP_VPORT_TYPE_GRE, { "gre", VPORT_FUNCTIONS(netdev_vport_get_status) }, - parse_tunnel_config, unparse_tunnel_config }, + parse_tunnel_config, unparse_tunnel_config, NULL }, { ODP_VPORT_TYPE_GRE, { "ipsec_gre", VPORT_FUNCTIONS(netdev_vport_get_status) }, - parse_tunnel_config, unparse_tunnel_config }, + parse_tunnel_config, unparse_tunnel_config, config_equal_ipsec }, { ODP_VPORT_TYPE_CAPWAP, { "capwap", VPORT_FUNCTIONS(netdev_vport_get_status) }, - parse_tunnel_config, unparse_tunnel_config }, + parse_tunnel_config, unparse_tunnel_config, NULL }, { ODP_VPORT_TYPE_PATCH, { "patch", VPORT_FUNCTIONS(NULL) }, - parse_patch_config, unparse_patch_config } + parse_patch_config, unparse_patch_config, NULL } }; int i;