cbac50e544aeeeb683bc51f32619194a749b8370
[cascardo/ovs.git] / ovn / controller / pinctrl.c
1 /* Copyright (c) 2015, 2016 Red Hat, Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <config.h>
17
18 #include "pinctrl.h"
19
20 #include "coverage.h"
21 #include "dirs.h"
22 #include "dp-packet.h"
23 #include "flow.h"
24 #include "lport.h"
25 #include "openvswitch/ofp-actions.h"
26 #include "openvswitch/ofp-msgs.h"
27 #include "openvswitch/ofp-print.h"
28 #include "openvswitch/ofp-util.h"
29 #include "openvswitch/vlog.h"
30 #include "ovn-controller.h"
31 #include "ovn/lib/actions.h"
32 #include "ovn/lib/logical-fields.h"
33 #include "poll-loop.h"
34 #include "rconn.h"
35 #include "socket-util.h"
36 #include "timeval.h"
37 #include "vswitch-idl.h"
38
39 VLOG_DEFINE_THIS_MODULE(pinctrl);
40
41 /* OpenFlow connection to the switch. */
42 static struct rconn *swconn;
43
44 /* Last seen sequence number for 'swconn'.  When this differs from
45  * rconn_get_connection_seqno(rconn), 'swconn' has reconnected. */
46 static unsigned int conn_seq_no;
47
48 static void pinctrl_handle_put_arp(const struct flow *md,
49                                    const struct flow *headers);
50 static void init_put_arps(void);
51 static void destroy_put_arps(void);
52 static void run_put_arps(struct controller_ctx *,
53                          const struct lport_index *lports);
54 static void wait_put_arps(struct controller_ctx *);
55 static void flush_put_arps(void);
56
57 COVERAGE_DEFINE(pinctrl_drop_put_arp);
58
59 void
60 pinctrl_init(void)
61 {
62     swconn = rconn_create(5, 0, DSCP_DEFAULT, 1 << OFP13_VERSION);
63     conn_seq_no = 0;
64     init_put_arps();
65 }
66
67 static ovs_be32
68 queue_msg(struct ofpbuf *msg)
69 {
70     const struct ofp_header *oh = msg->data;
71     ovs_be32 xid = oh->xid;
72
73     rconn_send(swconn, msg, NULL);
74     return xid;
75 }
76
77 /* Sets up 'swconn', a newly (re)connected connection to a switch. */
78 static void
79 pinctrl_setup(struct rconn *swconn)
80 {
81     /* Fetch the switch configuration.  The response later will allow us to
82      * change the miss_send_len to UINT16_MAX, so that we can enable
83      * asynchronous messages. */
84     queue_msg(ofpraw_alloc(OFPRAW_OFPT_GET_CONFIG_REQUEST,
85                            rconn_get_version(swconn), 0));
86
87     /* Set a packet-in format that supports userdata.  */
88     queue_msg(ofputil_make_set_packet_in_format(rconn_get_version(swconn),
89                                                 NXPIF_NXT_PACKET_IN2));
90 }
91
92 static void
93 set_switch_config(struct rconn *swconn,
94                   const struct ofputil_switch_config *config)
95 {
96     enum ofp_version version = rconn_get_version(swconn);
97     struct ofpbuf *request = ofputil_encode_set_config(config, version);
98     queue_msg(request);
99 }
100
101 static void
102 pinctrl_handle_arp(const struct flow *ip_flow, const struct match *md,
103                    struct ofpbuf *userdata)
104 {
105     /* This action only works for IP packets, and the switch should only send
106      * us IP packets this way, but check here just to be sure. */
107     if (ip_flow->dl_type != htons(ETH_TYPE_IP)) {
108         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
109         VLOG_WARN_RL(&rl, "ARP action on non-IP packet (Ethertype %"PRIx16")",
110                      ntohs(ip_flow->dl_type));
111         return;
112     }
113
114     /* Compose an ARP packet. */
115     uint64_t packet_stub[128 / 8];
116     struct dp_packet packet;
117     dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub);
118     compose_arp__(&packet);
119
120     struct eth_header *eth = dp_packet_l2(&packet);
121     eth->eth_dst = ip_flow->dl_dst;
122     eth->eth_src = ip_flow->dl_src;
123
124     struct arp_eth_header *arp = dp_packet_l3(&packet);
125     arp->ar_op = htons(ARP_OP_REQUEST);
126     arp->ar_sha = ip_flow->dl_src;
127     put_16aligned_be32(&arp->ar_spa, ip_flow->nw_src);
128     arp->ar_tha = eth_addr_zero;
129     put_16aligned_be32(&arp->ar_tpa, ip_flow->nw_dst);
130
131     if (ip_flow->vlan_tci & htons(VLAN_CFI)) {
132         eth_push_vlan(&packet, htons(ETH_TYPE_VLAN_8021Q), ip_flow->vlan_tci);
133     }
134
135     /* Compose actions.
136      *
137      * First, copy metadata from 'md' into the packet-out via "set_field"
138      * actions, then add actions from 'userdata'.
139      */
140     uint64_t ofpacts_stub[4096 / 8];
141     struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
142     enum ofp_version version = rconn_get_version(swconn);
143
144     enum mf_field_id md_fields[] = {
145 #if FLOW_N_REGS == 8
146         MFF_REG0,
147         MFF_REG1,
148         MFF_REG2,
149         MFF_REG3,
150         MFF_REG4,
151         MFF_REG5,
152         MFF_REG6,
153         MFF_REG7,
154 #else
155 #error
156 #endif
157         MFF_METADATA,
158     };
159     for (size_t i = 0; i < ARRAY_SIZE(md_fields); i++) {
160         const struct mf_field *field = mf_from_id(md_fields[i]);
161         if (!mf_is_all_wild(field, &md->wc)) {
162             struct ofpact_set_field *sf = ofpact_put_SET_FIELD(&ofpacts);
163             sf->field = field;
164             sf->flow_has_vlan = false;
165             mf_get_value(field, &md->flow, &sf->value);
166             memset(&sf->mask, 0xff, field->n_bytes);
167         }
168     }
169     enum ofperr error = ofpacts_pull_openflow_actions(userdata, userdata->size,
170                                                       version, &ofpacts);
171     if (error) {
172         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
173         VLOG_WARN_RL(&rl, "failed to parse arp actions (%s)",
174                      ofperr_to_string(error));
175         goto exit;
176     }
177
178     struct ofputil_packet_out po = {
179         .packet = dp_packet_data(&packet),
180         .packet_len = dp_packet_size(&packet),
181         .buffer_id = UINT32_MAX,
182         .in_port = OFPP_CONTROLLER,
183         .ofpacts = ofpacts.data,
184         .ofpacts_len = ofpacts.size,
185     };
186     enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version);
187     queue_msg(ofputil_encode_packet_out(&po, proto));
188
189 exit:
190     dp_packet_uninit(&packet);
191     ofpbuf_uninit(&ofpacts);
192 }
193
194 static void
195 process_packet_in(const struct ofp_header *msg)
196 {
197     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
198
199     struct ofputil_packet_in pin;
200     enum ofperr error = ofputil_decode_packet_in(msg, true, &pin,
201                                                  NULL, NULL, NULL);
202     if (error) {
203         VLOG_WARN_RL(&rl, "error decoding packet-in: %s",
204                      ofperr_to_string(error));
205         return;
206     }
207     if (pin.reason != OFPR_ACTION) {
208         return;
209     }
210
211     struct ofpbuf userdata = ofpbuf_const_initializer(pin.userdata,
212                                                       pin.userdata_len);
213     const struct action_header *ah = ofpbuf_pull(&userdata, sizeof *ah);
214     if (!ah) {
215         VLOG_WARN_RL(&rl, "packet-in userdata lacks action header");
216         return;
217     }
218
219     struct dp_packet packet;
220     dp_packet_use_const(&packet, pin.packet, pin.packet_len);
221     struct flow headers;
222     flow_extract(&packet, &headers);
223
224     switch (ntohl(ah->opcode)) {
225     case ACTION_OPCODE_ARP:
226         pinctrl_handle_arp(&headers, &pin.flow_metadata, &userdata);
227         break;
228
229     case ACTION_OPCODE_PUT_ARP:
230         pinctrl_handle_put_arp(&pin.flow_metadata.flow, &headers);
231         break;
232
233     default:
234         VLOG_WARN_RL(&rl, "unrecognized packet-in opcode %"PRIu32,
235                      ntohl(ah->opcode));
236         break;
237     }
238 }
239
240 static void
241 pinctrl_recv(const struct ofp_header *oh, enum ofptype type)
242 {
243     if (type == OFPTYPE_ECHO_REQUEST) {
244         queue_msg(make_echo_reply(oh));
245     } else if (type == OFPTYPE_GET_CONFIG_REPLY) {
246         /* Enable asynchronous messages (see "Asynchronous Messages" in
247          * DESIGN.md for more information). */
248         struct ofputil_switch_config config;
249
250         ofputil_decode_get_config_reply(oh, &config);
251         config.miss_send_len = UINT16_MAX;
252         set_switch_config(swconn, &config);
253     } else if (type == OFPTYPE_PACKET_IN) {
254         process_packet_in(oh);
255     } else if (type != OFPTYPE_ECHO_REPLY && type != OFPTYPE_BARRIER_REPLY) {
256         if (VLOG_IS_DBG_ENABLED()) {
257             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300);
258
259             char *s = ofp_to_string(oh, ntohs(oh->length), 2);
260
261             VLOG_DBG_RL(&rl, "OpenFlow packet ignored: %s", s);
262             free(s);
263         }
264     }
265 }
266
267 void
268 pinctrl_run(struct controller_ctx *ctx, const struct lport_index *lports,
269             const struct ovsrec_bridge *br_int)
270 {
271     if (br_int) {
272         char *target;
273
274         target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name);
275         if (strcmp(target, rconn_get_target(swconn))) {
276             VLOG_INFO("%s: connecting to switch", target);
277             rconn_connect(swconn, target, target);
278         }
279         free(target);
280     } else {
281         rconn_disconnect(swconn);
282     }
283
284     rconn_run(swconn);
285
286     if (rconn_is_connected(swconn)) {
287         if (conn_seq_no != rconn_get_connection_seqno(swconn)) {
288             pinctrl_setup(swconn);
289             conn_seq_no = rconn_get_connection_seqno(swconn);
290             flush_put_arps();
291         }
292
293         /* Process a limited number of messages per call. */
294         for (int i = 0; i < 50; i++) {
295             struct ofpbuf *msg = rconn_recv(swconn);
296             if (!msg) {
297                 break;
298             }
299
300             const struct ofp_header *oh = msg->data;
301             enum ofptype type;
302
303             ofptype_decode(&type, oh);
304             pinctrl_recv(oh, type);
305             ofpbuf_delete(msg);
306         }
307     }
308
309     run_put_arps(ctx, lports);
310 }
311
312 void
313 pinctrl_wait(struct controller_ctx *ctx)
314 {
315     wait_put_arps(ctx);
316     rconn_run_wait(swconn);
317     rconn_recv_wait(swconn);
318 }
319
320 void
321 pinctrl_destroy(void)
322 {
323     rconn_destroy(swconn);
324     destroy_put_arps();
325 }
326 \f
327 /* Implementation of the "put_arp" OVN action.  This action sends a packet to
328  * ovn-controller, using the flow as an API (see actions.h for details).  This
329  * code implements the action by updating the MAC_Binding table in the
330  * southbound database.
331  *
332  * This code could be a lot simpler if the database could always be updated,
333  * but in fact we can only update it when ctx->ovnsb_idl_txn is nonnull.  Thus,
334  * we buffer up a few put_arps (but we don't keep them longer than 1 second)
335  * and apply them whenever a database transaction is available. */
336
337 /* Buffered "put_arp" operation. */
338 struct put_arp {
339     struct hmap_node hmap_node; /* In 'put_arps'. */
340
341     long long int timestamp;    /* In milliseconds. */
342
343     /* Key. */
344     uint32_t dp_key;
345     uint32_t port_key;
346     ovs_be32 ip;
347
348     /* Value. */
349     struct eth_addr mac;
350 };
351
352 /* Contains "struct put_arp"s. */
353 static struct hmap put_arps;
354
355 static void
356 init_put_arps(void)
357 {
358     hmap_init(&put_arps);
359 }
360
361 static void
362 destroy_put_arps(void)
363 {
364     flush_put_arps();
365     hmap_destroy(&put_arps);
366 }
367
368 static struct put_arp *
369 pinctrl_find_put_arp(uint32_t dp_key, uint32_t port_key, ovs_be32 ip,
370                      uint32_t hash)
371 {
372     struct put_arp *pa;
373     HMAP_FOR_EACH_WITH_HASH (pa, hmap_node, hash, &put_arps) {
374         if (pa->dp_key == dp_key
375             && pa->port_key == port_key
376             && pa->ip == ip) {
377             return pa;
378         }
379     }
380     return NULL;
381 }
382
383 static void
384 pinctrl_handle_put_arp(const struct flow *md, const struct flow *headers)
385 {
386     uint32_t dp_key = ntohll(md->metadata);
387     uint32_t port_key = md->regs[MFF_LOG_INPORT - MFF_REG0];
388     ovs_be32 ip = htonl(md->regs[0]);
389     uint32_t hash = hash_3words(dp_key, port_key, (OVS_FORCE uint32_t) ip);
390     struct put_arp *pa = pinctrl_find_put_arp(dp_key, port_key, ip, hash);
391     if (!pa) {
392         if (hmap_count(&put_arps) >= 1000) {
393             COVERAGE_INC(pinctrl_drop_put_arp);
394             return;
395         }
396
397         pa = xmalloc(sizeof *pa);
398         hmap_insert(&put_arps, &pa->hmap_node, hash);
399         pa->dp_key = dp_key;
400         pa->port_key = port_key;
401         pa->ip = ip;
402     }
403     pa->timestamp = time_msec();
404     pa->mac = headers->dl_src;
405 }
406
407 static void
408 run_put_arp(struct controller_ctx *ctx, const struct lport_index *lports,
409             const struct put_arp *pa)
410 {
411     if (time_msec() > pa->timestamp + 1000) {
412         return;
413     }
414
415     /* Convert logical datapath and logical port key into lport. */
416     const struct sbrec_port_binding *pb
417         = lport_lookup_by_key(lports, pa->dp_key, pa->port_key);
418     if (!pb) {
419         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
420
421         VLOG_WARN_RL(&rl, "unknown logical port with datapath %"PRIu32" "
422                      "and port %"PRIu32, pa->dp_key, pa->port_key);
423         return;
424     }
425
426     /* Convert arguments to string form for database. */
427     char ip_string[INET_ADDRSTRLEN + 1];
428     snprintf(ip_string, sizeof ip_string, IP_FMT, IP_ARGS(pa->ip));
429
430     char mac_string[ETH_ADDR_STRLEN + 1];
431     snprintf(mac_string, sizeof mac_string,
432              ETH_ADDR_FMT, ETH_ADDR_ARGS(pa->mac));
433
434     /* Check for and update an existing IP-MAC binding for this logical
435      * port.
436      *
437      * XXX This is not very efficient. */
438     const struct sbrec_mac_binding *b;
439     SBREC_MAC_BINDING_FOR_EACH (b, ctx->ovnsb_idl) {
440         if (!strcmp(b->logical_port, pb->logical_port)
441             && !strcmp(b->ip, ip_string)) {
442             if (strcmp(b->mac, mac_string)) {
443                 sbrec_mac_binding_set_mac(b, mac_string);
444             }
445             return;
446         }
447     }
448
449     /* Add new IP-MAC binding for this logical port. */
450     b = sbrec_mac_binding_insert(ctx->ovnsb_idl_txn);
451     sbrec_mac_binding_set_logical_port(b, pb->logical_port);
452     sbrec_mac_binding_set_ip(b, ip_string);
453     sbrec_mac_binding_set_mac(b, mac_string);
454 }
455
456 static void
457 run_put_arps(struct controller_ctx *ctx, const struct lport_index *lports)
458 {
459     if (!ctx->ovnsb_idl_txn) {
460         return;
461     }
462
463     const struct put_arp *pa;
464     HMAP_FOR_EACH (pa, hmap_node, &put_arps) {
465         run_put_arp(ctx, lports, pa);
466     }
467     flush_put_arps();
468 }
469
470 static void
471 wait_put_arps(struct controller_ctx *ctx)
472 {
473     if (ctx->ovnsb_idl_txn && !hmap_is_empty(&put_arps)) {
474         poll_immediate_wake();
475     }
476 }
477
478 static void
479 flush_put_arps(void)
480 {
481     struct put_arp *pa, *next;
482     HMAP_FOR_EACH_SAFE (pa, next, hmap_node, &put_arps) {
483         hmap_remove(&put_arps, &pa->hmap_node);
484         free(pa);
485     }
486 }