2 /* Copyright (c) 2015 Red Hat, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include "ofp-print.h"
24 #include "openvswitch/vlog.h"
25 #include "socket-util.h"
26 #include "vswitch-idl.h"
28 VLOG_DEFINE_THIS_MODULE(pinctrl);
30 /* OpenFlow connection to the switch. */
31 static struct rconn *swconn;
33 /* Last seen sequence number for 'swconn'. When this differs from
34 * rconn_get_connection_seqno(rconn), 'swconn' has reconnected. */
35 static unsigned int conn_seq_no;
40 swconn = rconn_create(5, 0, DSCP_DEFAULT, 1 << OFP13_VERSION);
45 queue_msg(struct ofpbuf *msg)
47 const struct ofp_header *oh = msg->data;
48 ovs_be32 xid = oh->xid;
50 rconn_send(swconn, msg, NULL);
55 get_switch_config(struct rconn *swconn)
57 struct ofpbuf *request;
59 request = ofpraw_alloc(OFPRAW_OFPT_GET_CONFIG_REQUEST,
60 rconn_get_version(swconn), 0);
65 set_switch_config(struct rconn *swconn, const struct ofp_switch_config *config)
67 struct ofpbuf *request;
70 ofpraw_alloc(OFPRAW_OFPT_SET_CONFIG, rconn_get_version(swconn), 0);
71 ofpbuf_put(request, config, sizeof *config);
77 process_packet_in(struct controller_ctx *ctx OVS_UNUSED,
78 const struct ofp_header *msg)
80 struct ofputil_packet_in pin;
84 if (ofputil_decode_packet_in(msg, &pin, &total_len, &buffer_id) != 0) {
87 if (pin.reason != OFPR_ACTION) {
91 /* XXX : process the received packet */
95 pinctrl_recv(struct controller_ctx *ctx, const struct ofp_header *oh,
98 if (type == OFPTYPE_ECHO_REQUEST) {
99 queue_msg(make_echo_reply(oh));
100 } else if (type == OFPTYPE_GET_CONFIG_REPLY) {
101 struct ofpbuf rq_buf;
102 struct ofp_switch_config *config_, config;
104 ofpbuf_use_const(&rq_buf, oh, ntohs(oh->length));
105 config_ = ofpbuf_pull(&rq_buf, sizeof *config_);
107 config.miss_send_len = htons(UINT16_MAX);
108 set_switch_config(swconn, &config);
109 } else if (type == OFPTYPE_PACKET_IN) {
110 process_packet_in(ctx, oh);
111 } else if (type != OFPTYPE_ECHO_REPLY && type != OFPTYPE_BARRIER_REPLY) {
112 if (VLOG_IS_DBG_ENABLED()) {
113 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300);
115 char *s = ofp_to_string(oh, ntohs(oh->length), 2);
117 VLOG_DBG_RL(&rl, "OpenFlow packet ignored: %s", s);
124 pinctrl_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int)
129 target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name);
130 if (strcmp(target, rconn_get_target(swconn))) {
131 VLOG_INFO("%s: connecting to switch", target);
132 rconn_connect(swconn, target, target);
136 rconn_disconnect(swconn);
141 if (!rconn_is_connected(swconn)) {
145 if (conn_seq_no != rconn_get_connection_seqno(swconn)) {
146 get_switch_config(swconn);
147 conn_seq_no = rconn_get_connection_seqno(swconn);
150 struct ofpbuf *msg = rconn_recv(swconn);
156 const struct ofp_header *oh = msg->data;
159 ofptype_decode(&type, oh);
160 pinctrl_recv(ctx, oh, type);
167 rconn_run_wait(swconn);
168 rconn_recv_wait(swconn);
172 pinctrl_destroy(void)
174 rconn_destroy(swconn);