X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=c44762c467f0c4f0153102446114d33dfcc1109b;hb=680b8c67669e88a6d45c8cc36579230ad8ebc09e;hp=3ab9cc9992c1162a836f1702caa67a51e5c91698;hpb=fe55ad159d8fd396a9e4914a03eea93d096d03b1;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 3ab9cc99..c44762c4 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -34,10 +34,10 @@ #include "netflow.h" #include "odp-util.h" #include "ofp-print.h" +#include "ofproto-sflow.h" #include "ofpbuf.h" #include "openflow/nicira-ext.h" #include "openflow/openflow.h" -#include "openflow/openflow-mgmt.h" #include "openvswitch/datapath-protocol.h" #include "packets.h" #include "pinsched.h" @@ -59,10 +59,7 @@ #define THIS_MODULE VLM_ofproto #include "vlog.h" -enum { - DP_GROUP_FLOOD = 0, - DP_GROUP_ALL = 1 -}; +#include "sflow_api.h" enum { TABLEID_HASH = 0, @@ -185,7 +182,6 @@ struct ofproto { /* Settings. */ uint64_t datapath_id; /* Datapath ID. */ uint64_t fallback_dpid; /* Datapath ID if no better choice found. */ - uint64_t mgmt_id; /* Management channel identifier. */ char *manufacturer; /* Manufacturer. */ char *hardware; /* Hardware. */ char *software; /* Software version. */ @@ -207,6 +203,7 @@ struct ofproto { struct fail_open *fail_open; struct pinsched *miss_sched, *action_sched; struct netflow *netflow; + struct ofproto_sflow *sflow; /* Flow table. */ struct classifier cls; @@ -251,13 +248,15 @@ static void handle_odp_msg(struct ofproto *, struct ofpbuf *); static void handle_openflow(struct ofconn *, struct ofproto *, struct ofpbuf *); -static void refresh_port_group(struct ofproto *, unsigned int group); +static void refresh_port_groups(struct ofproto *); + static void update_port(struct ofproto *, const char *devname); static int init_ports(struct ofproto *); static void reinit_ports(struct ofproto *); int -ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux, +ofproto_create(const char *datapath, const char *datapath_type, + const struct ofhooks *ofhooks, void *aux, struct ofproto **ofprotop) { struct odp_stats stats; @@ -268,7 +267,7 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux, *ofprotop = NULL; /* Connect to datapath and start listening for messages. */ - error = dpif_open(datapath, &dpif); + error = dpif_open(datapath, datapath_type, &dpif); if (error) { VLOG_ERR("failed to open datapath %s: %s", datapath, strerror(error)); return error; @@ -280,7 +279,7 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux, dpif_close(dpif); return error; } - error = dpif_recv_set_mask(dpif, ODPL_MISS | ODPL_ACTION); + error = dpif_recv_set_mask(dpif, ODPL_MISS | ODPL_ACTION | ODPL_SFLOW); if (error) { VLOG_ERR("failed to listen on datapath %s: %s", datapath, strerror(error)); @@ -313,6 +312,7 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux, p->fail_open = NULL; p->miss_sched = p->action_sched = NULL; p->netflow = NULL; + p->sflow = NULL; /* Initialize flow table. */ classifier_init(&p->cls); @@ -345,13 +345,6 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux, p->ss_cat = switch_status_register(p->switch_status, "remote", rconn_status_cb, p->controller->rconn); - /* Almost done... */ - error = init_ports(p); - if (error) { - ofproto_destroy(p); - return error; - } - /* Pick final datapath ID. */ p->datapath_id = pick_datapath_id(p); VLOG_INFO("using datapath ID %012"PRIx64, p->datapath_id); @@ -371,12 +364,6 @@ ofproto_set_datapath_id(struct ofproto *p, uint64_t datapath_id) } } -void -ofproto_set_mgmt_id(struct ofproto *p, uint64_t mgmt_id) -{ - p->mgmt_id = mgmt_id; -} - void ofproto_set_probe_interval(struct ofproto *p, int probe_interval) { @@ -545,6 +532,30 @@ ofproto_set_netflow(struct ofproto *ofproto, } } +void +ofproto_set_sflow(struct ofproto *ofproto, + const struct ofproto_sflow_options *oso) +{ + struct ofproto_sflow *os = ofproto->sflow; + if (oso) { + if (!os) { + struct ofport *ofport; + unsigned int odp_port; + + os = ofproto->sflow = ofproto_sflow_create(ofproto->dpif); + refresh_port_groups(ofproto); + PORT_ARRAY_FOR_EACH (ofport, &ofproto->ports, odp_port) { + ofproto_sflow_add_port(os, odp_port, + netdev_get_name(ofport->netdev)); + } + } + ofproto_sflow_set_options(os, oso); + } else { + ofproto_sflow_destroy(os); + ofproto->sflow = NULL; + } +} + void ofproto_set_failure(struct ofproto *ofproto, bool fail_open) { @@ -606,12 +617,6 @@ ofproto_get_datapath_id(const struct ofproto *ofproto) return ofproto->datapath_id; } -uint64_t -ofproto_get_mgmt_id(const struct ofproto *ofproto) -{ - return ofproto->mgmt_id; -} - int ofproto_get_probe_interval(const struct ofproto *ofproto) { @@ -696,6 +701,7 @@ ofproto_destroy(struct ofproto *p) pinsched_destroy(p->miss_sched); pinsched_destroy(p->action_sched); netflow_destroy(p->netflow); + ofproto_sflow_destroy(p->sflow); switch_status_unregister(p->ss_cat); @@ -743,6 +749,10 @@ ofproto_run1(struct ofproto *p) int error; int i; + if (shash_is_empty(&p->port_by_name)) { + init_ports(p); + } + for (i = 0; i < 50; i++) { struct ofpbuf *buf; int error; @@ -845,6 +855,9 @@ ofproto_run1(struct ofproto *p) if (p->netflow) { netflow_run(p->netflow); } + if (p->sflow) { + ofproto_sflow_run(p->sflow); + } return 0; } @@ -898,6 +911,9 @@ ofproto_wait(struct ofproto *p) } pinsched_wait(p->miss_sched); pinsched_wait(p->action_sched); + if (p->sflow) { + ofproto_sflow_wait(p->sflow); + } if (!tag_set_is_empty(&p->revalidate_set)) { poll_immediate_wake(); } @@ -1038,7 +1054,7 @@ reinit_ports(struct ofproto *p) svec_destroy(&devnames); } -static void +static size_t refresh_port_group(struct ofproto *p, unsigned int group) { uint16_t *ports; @@ -1057,25 +1073,36 @@ refresh_port_group(struct ofproto *p, unsigned int group) } dpif_port_group_set(p->dpif, group, ports, n_ports); free(ports); + + return n_ports; } static void refresh_port_groups(struct ofproto *p) { - refresh_port_group(p, DP_GROUP_FLOOD); - refresh_port_group(p, DP_GROUP_ALL); + size_t n_flood = refresh_port_group(p, DP_GROUP_FLOOD); + size_t n_all = refresh_port_group(p, DP_GROUP_ALL); + if (p->sflow) { + ofproto_sflow_set_group_sizes(p->sflow, n_flood, n_all); + } } static struct ofport * make_ofport(const struct odp_port *odp_port) { + struct netdev_options netdev_options; enum netdev_flags flags; struct ofport *ofport; struct netdev *netdev; bool carrier; int error; - error = netdev_open(odp_port->devname, NETDEV_ETH_TYPE_NONE, &netdev); + memset(&netdev_options, 0, sizeof netdev_options); + netdev_options.name = odp_port->devname; + netdev_options.ethertype = NETDEV_ETH_TYPE_NONE; + netdev_options.may_open = true; + + error = netdev_open(&netdev_options, &netdev); if (error) { VLOG_WARN_RL(&rl, "ignoring port %s (%"PRIu16") because netdev %s " "cannot be opened (%s)", @@ -1162,19 +1189,29 @@ send_port_status(struct ofproto *p, const struct ofport *ofport, static void ofport_install(struct ofproto *p, struct ofport *ofport) { + uint16_t odp_port = ofp_port_to_odp_port(ofport->opp.port_no); + const char *netdev_name = (const char *) ofport->opp.name; + netdev_monitor_add(p->netdev_monitor, ofport->netdev); - port_array_set(&p->ports, ofp_port_to_odp_port(ofport->opp.port_no), - ofport); - shash_add(&p->port_by_name, (char *) ofport->opp.name, ofport); + port_array_set(&p->ports, odp_port, ofport); + shash_add(&p->port_by_name, netdev_name, ofport); + if (p->sflow) { + ofproto_sflow_add_port(p->sflow, odp_port, netdev_name); + } } static void ofport_remove(struct ofproto *p, struct ofport *ofport) { + uint16_t odp_port = ofp_port_to_odp_port(ofport->opp.port_no); + netdev_monitor_remove(p->netdev_monitor, ofport->netdev); - port_array_set(&p->ports, ofp_port_to_odp_port(ofport->opp.port_no), NULL); + port_array_set(&p->ports, odp_port, NULL); shash_delete(&p->port_by_name, shash_find(&p->port_by_name, (char *) ofport->opp.name)); + if (p->sflow) { + ofproto_sflow_del_port(p->sflow, odp_port); + } } static void @@ -2259,7 +2296,7 @@ update_port_config(struct ofproto *p, struct ofport *port, #undef REVALIDATE_BITS if (mask & OFPPC_NO_FLOOD) { port->opp.config ^= OFPPC_NO_FLOOD; - refresh_port_group(p, DP_GROUP_FLOOD); + refresh_port_groups(p); } if (mask & OFPPC_NO_PACKET_IN) { port->opp.config ^= OFPPC_NO_PACKET_IN; @@ -2918,58 +2955,6 @@ handle_flow_mod(struct ofproto *p, struct ofconn *ofconn, } } -static void -send_capability_reply(struct ofproto *p, struct ofconn *ofconn, uint32_t xid) -{ - struct ofmp_capability_reply *ocr; - struct ofpbuf *b; - char capabilities[] = "com.nicira.mgmt.manager=false\n"; - - ocr = make_openflow_xid(sizeof(*ocr), OFPT_VENDOR, xid, &b); - ocr->header.header.vendor = htonl(NX_VENDOR_ID); - ocr->header.header.subtype = htonl(NXT_MGMT); - ocr->header.type = htons(OFMPT_CAPABILITY_REPLY); - - ocr->format = htonl(OFMPCOF_SIMPLE); - ocr->mgmt_id = htonll(p->mgmt_id); - - ofpbuf_put(b, capabilities, strlen(capabilities)); - - queue_tx(b, ofconn, ofconn->reply_counter); -} - -static int -handle_ofmp(struct ofproto *p, struct ofconn *ofconn, - struct ofmp_header *ofmph) -{ - size_t msg_len = ntohs(ofmph->header.header.length); - if (msg_len < sizeof(*ofmph)) { - VLOG_WARN_RL(&rl, "dropping short managment message: %zu\n", msg_len); - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH); - } - - if (ofmph->type == htons(OFMPT_CAPABILITY_REQUEST)) { - struct ofmp_capability_request *ofmpcr; - - if (msg_len < sizeof(struct ofmp_capability_request)) { - VLOG_WARN_RL(&rl, "dropping short capability request: %zu\n", - msg_len); - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH); - } - - ofmpcr = (struct ofmp_capability_request *)ofmph; - if (ofmpcr->format != htonl(OFMPCAF_SIMPLE)) { - /* xxx Find a better type than bad subtype */ - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE); - } - - send_capability_reply(p, ofconn, ofmph->header.header.xid); - return 0; - } else { - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE); - } -} - static int handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg) { @@ -2991,15 +2976,6 @@ handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg) case NXT_STATUS_REQUEST: return switch_status_handle_request(p->switch_status, ofconn->rconn, msg); - - case NXT_ACT_SET_CONFIG: - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE); /* XXX */ - - case NXT_ACT_GET_CONFIG: - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE); /* XXX */ - - case NXT_MGMT: - return handle_ofmp(p, ofconn, msg); } return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE); @@ -3070,7 +3046,7 @@ handle_openflow(struct ofconn *ofconn, struct ofproto *p, } static void -handle_odp_msg(struct ofproto *p, struct ofpbuf *packet) +handle_odp_miss_msg(struct ofproto *p, struct ofpbuf *packet) { struct odp_msg *msg = packet->data; uint16_t in_port = odp_port_to_ofp_port(msg->port); @@ -3078,14 +3054,6 @@ handle_odp_msg(struct ofproto *p, struct ofpbuf *packet) struct ofpbuf payload; flow_t flow; - /* Handle controller actions. */ - if (msg->type == _ODPL_ACTION_NR) { - COVERAGE_INC(ofproto_ctlr_action); - pinsched_send(p->action_sched, in_port, packet, - send_packet_in_action, p); - return; - } - payload.data = msg + 1; payload.size = msg->length - sizeof *msg; flow_extract(&payload, msg->port, &flow); @@ -3155,6 +3123,36 @@ handle_odp_msg(struct ofproto *p, struct ofpbuf *packet) ofpbuf_delete(packet); } } + +static void +handle_odp_msg(struct ofproto *p, struct ofpbuf *packet) +{ + struct odp_msg *msg = packet->data; + + switch (msg->type) { + case _ODPL_ACTION_NR: + COVERAGE_INC(ofproto_ctlr_action); + pinsched_send(p->action_sched, odp_port_to_ofp_port(msg->port), packet, + send_packet_in_action, p); + break; + + case _ODPL_SFLOW_NR: + if (p->sflow) { + ofproto_sflow_received(p->sflow, msg); + } + ofpbuf_delete(packet); + break; + + case _ODPL_MISS_NR: + handle_odp_miss_msg(p, packet); + break; + + default: + VLOG_WARN_RL(&rl, "received ODP message of unexpected type %"PRIu32, + msg->type); + break; + } +} static void revalidate_cb(struct cls_rule *sub_, void *cbdata_)