X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdpif.c;h=9cbf877179d2f2d0848f6b342219a50cf1cd93d0;hb=408869427edc59058b6e7680e612b3a6cd46edc1;hp=c6940b149bb11760d6ea128255d8b48b49fe27eb;hpb=a8d9304d121f56af0e6f02677342933579be3277;p=openvswitch diff --git a/lib/dpif.c b/lib/dpif.c index c6940b14..9cbf8771 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -68,6 +68,7 @@ struct registered_dpif_class { int refcount; }; static struct shash dpif_classes = SHASH_INITIALIZER(&dpif_classes); +static struct sset dpif_blacklist = SSET_INITIALIZER(&dpif_blacklist); /* Rate limit for individual messages going to or from the datapath, output at * DBG level. This is very high because, if these are enabled, it is because @@ -108,6 +109,12 @@ dp_register_provider(const struct dpif_class *new_class) { struct registered_dpif_class *registered_class; + if (sset_contains(&dpif_blacklist, new_class->type)) { + VLOG_DBG("attempted to register blacklisted provider: %s", + new_class->type); + return EINVAL; + } + if (shash_find(&dpif_classes, new_class->type)) { VLOG_WARN("attempted to register duplicate datapath provider: %s", new_class->type); @@ -151,6 +158,14 @@ dp_unregister_provider(const char *type) return 0; } +/* Blacklists a provider. Causes future calls of dp_register_provider() with + * a dpif_class which implements 'type' to fail. */ +void +dp_blacklist_provider(const char *type) +{ + sset_add(&dpif_blacklist, type); +} + /* Clears 'types' and enumerates the types of all currently registered datapath * providers into it. The caller must first initialize the sset. */ void @@ -388,33 +403,6 @@ dpif_get_dp_stats(const struct dpif *dpif, struct dpif_dp_stats *stats) return error; } -/* Retrieves the current IP fragment handling policy for 'dpif' into - * '*drop_frags': true indicates that fragments are dropped, false indicates - * that fragments are treated in the same way as other IP packets (except that - * the L4 header cannot be read). Returns 0 if successful, otherwise a - * positive errno value. */ -int -dpif_get_drop_frags(const struct dpif *dpif, bool *drop_frags) -{ - int error = dpif->dpif_class->get_drop_frags(dpif, drop_frags); - if (error) { - *drop_frags = false; - } - log_operation(dpif, "get_drop_frags", error); - return error; -} - -/* Changes 'dpif''s treatment of IP fragments to 'drop_frags', whose meaning is - * the same as for the get_drop_frags member function. Returns 0 if - * successful, otherwise a positive errno value. */ -int -dpif_set_drop_frags(struct dpif *dpif, bool drop_frags) -{ - int error = dpif->dpif_class->set_drop_frags(dpif, drop_frags); - log_operation(dpif, "set_drop_frags", error); - return error; -} - /* Attempts to add 'netdev' as a port on 'dpif'. If successful, returns 0 and * sets '*port_nop' to the new port's port number (if 'port_nop' is non-null). * On failure, returns a positive errno value and sets '*port_nop' to @@ -542,6 +530,23 @@ dpif_get_max_ports(const struct dpif *dpif) return dpif->dpif_class->get_max_ports(dpif); } +/* Returns the Netlink PID value to supply in OVS_ACTION_ATTR_USERSPACE actions + * as the OVS_USERSPACE_ATTR_PID attribute's value, for use in flows whose + * packets arrived on port 'port_no'. + * + * The return value is only meaningful when DPIF_UC_ACTION has been enabled in + * the 'dpif''s listen mask. It is allowed to change when DPIF_UC_ACTION is + * disabled and then re-enabled, so a client that does that must be prepared to + * update all of the flows that it installed that contain + * OVS_ACTION_ATTR_USERSPACE actions. */ +uint32_t +dpif_port_get_pid(const struct dpif *dpif, uint16_t port_no) +{ + return (dpif->dpif_class->port_get_pid + ? (dpif->dpif_class->port_get_pid)(dpif, port_no) + : 0); +} + /* Looks up port number 'port_no' in 'dpif'. On success, returns 0 and copies * the port's name into the 'name_size' bytes in 'name', ensuring that the * result is null-terminated. On failure, returns a positive errno value and @@ -971,6 +976,51 @@ dpif_execute(struct dpif *dpif, return error; } +/* Executes each of the 'n_ops' operations in 'ops' on 'dpif', in the order in + * which they are specified, placing each operation's results in the "output" + * members documented in comments. + * + * This function exists because some datapaths can perform batched operations + * faster than individual operations. */ +void +dpif_operate(struct dpif *dpif, union dpif_op **ops, size_t n_ops) +{ + size_t i; + + if (dpif->dpif_class->operate) { + dpif->dpif_class->operate(dpif, ops, n_ops); + return; + } + + for (i = 0; i < n_ops; i++) { + union dpif_op *op = ops[i]; + struct dpif_flow_put *put; + struct dpif_execute *execute; + + switch (op->type) { + case DPIF_OP_FLOW_PUT: + put = &op->flow_put; + put->error = dpif_flow_put(dpif, put->flags, + put->key, put->key_len, + put->actions, put->actions_len, + put->stats); + break; + + case DPIF_OP_EXECUTE: + execute = &op->execute; + execute->error = dpif_execute(dpif, execute->key, execute->key_len, + execute->actions, + execute->actions_len, + execute->packet); + break; + + default: + NOT_REACHED(); + } + } +} + + /* Returns a string that represents 'type', for use in log messages. */ const char * dpif_upcall_type_to_string(enum dpif_upcall_type type) @@ -1008,7 +1058,12 @@ dpif_recv_get_mask(const struct dpif *dpif, int *listen_mask) /* Sets 'dpif''s "listen mask" to 'listen_mask'. A 1-bit of value 2**X set in * '*listen_mask' requests that dpif_recv() will receive messages of the type * (from "enum dpif_upcall_type") with value X. Returns 0 if successful, - * otherwise a positive errno value. */ + * otherwise a positive errno value. + * + * Turning DPIF_UC_ACTION off and then back on may change the Netlink PID + * assignments returned by dpif_port_get_pid(). If the client does this, it + * must update all of the flows that have OVS_ACTION_ATTR_USERSPACE actions + * using the new PID assignment. */ int dpif_recv_set_mask(struct dpif *dpif, int listen_mask) { @@ -1055,6 +1110,8 @@ dpif_recv(struct dpif *dpif, struct dpif_upcall *upcall) ds_destroy(&flow); free(packet); + } else if (error && error != EAGAIN) { + log_operation(dpif, "recv", error); } return error; } @@ -1089,9 +1146,9 @@ dpif_get_netflow_ids(const struct dpif *dpif, } /* Translates OpenFlow queue ID 'queue_id' (in host byte order) into a priority - * value for use in the OVS_ACTION_ATTR_SET_PRIORITY action. On success, - * returns 0 and stores the priority into '*priority'. On failure, returns a - * positive errno value and stores 0 into '*priority'. */ + * value used for setting packet priority. + * On success, returns 0 and stores the priority into '*priority'. + * On failure, returns a positive errno value and stores 0 into '*priority'. */ int dpif_queue_to_priority(const struct dpif *dpif, uint32_t queue_id, uint32_t *priority)