| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2017-03-17 13:38:55 -07:00
										 |  |  |  * Copyright (c) 2014, 2015, 2016, 2017 Nicira, Inc. | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <config.h>
 | 
					
						
							| 
									
										
										
										
											2015-09-04 14:40:08 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "ovs-router.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-06 14:42:32 -08:00
										 |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <netinet/in.h>
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | #include <arpa/inet.h>
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #include <inttypes.h>
 | 
					
						
							|  |  |  | #include <sys/socket.h>
 | 
					
						
							|  |  |  | #include <net/if.h>
 | 
					
						
							|  |  |  | #include <stdarg.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "classifier.h"
 | 
					
						
							|  |  |  | #include "command-line.h"
 | 
					
						
							|  |  |  | #include "compiler.h"
 | 
					
						
							|  |  |  | #include "dpif.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-29 16:40:21 -03:00
										 |  |  | #include "fatal-signal.h"
 | 
					
						
							| 
									
										
										
										
											2016-03-03 10:20:46 -08:00
										 |  |  | #include "openvswitch/dynamic-string.h"
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | #include "netdev.h"
 | 
					
						
							|  |  |  | #include "packets.h"
 | 
					
						
							| 
									
										
										
										
											2014-11-11 11:53:47 -08:00
										 |  |  | #include "seq.h"
 | 
					
						
							| 
									
										
										
										
											2014-11-14 15:58:09 -08:00
										 |  |  | #include "ovs-thread.h"
 | 
					
						
							| 
									
										
										
										
											2014-11-17 14:40:22 +09:00
										 |  |  | #include "route-table.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-03 00:42:34 -07:00
										 |  |  | #include "tnl-ports.h"
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | #include "unixctl.h"
 | 
					
						
							|  |  |  | #include "util.h"
 | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  | #include "unaligned.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  | #include "openvswitch/vlog.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | VLOG_DEFINE_THIS_MODULE(ovs_router); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-14 15:58:09 -08:00
										 |  |  | static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | static struct classifier cls; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 17:12:55 -07:00
										 |  |  | /* By default, use the system routing table.  For system-independent testing,
 | 
					
						
							|  |  |  |  * the unit tests disable using the system routing table. */ | 
					
						
							|  |  |  | static bool use_system_routing_table = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | struct ovs_router_entry { | 
					
						
							|  |  |  |     struct cls_rule cr; | 
					
						
							|  |  |  |     char output_bridge[IFNAMSIZ]; | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     struct in6_addr gw; | 
					
						
							|  |  |  |     struct in6_addr nw_addr; | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |     struct in6_addr src_addr; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     uint8_t plen; | 
					
						
							|  |  |  |     uint8_t priority; | 
					
						
							| 
									
										
										
										
											2018-04-18 11:03:47 +08:00
										 |  |  |     bool local; | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     uint32_t mark; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct ovs_router_entry * | 
					
						
							|  |  |  | ovs_router_entry_cast(const struct cls_rule *cr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-01-31 14:09:30 -08:00
										 |  |  |     return cr ? CONTAINER_OF(cr, struct ovs_router_entry, cr) : NULL; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 17:12:55 -07:00
										 |  |  | /* Disables obtaining routes from the system routing table, for testing
 | 
					
						
							|  |  |  |  * purposes. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | ovs_router_disable_system_routing_table(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     use_system_routing_table = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  | static bool | 
					
						
							|  |  |  | ovs_router_lookup_fallback(const struct in6_addr *ip6_dst, char output_bridge[], | 
					
						
							|  |  |  |                            struct in6_addr *src6, struct in6_addr *gw6) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ovs_be32 src; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 17:12:55 -07:00
										 |  |  |     if (!use_system_routing_table | 
					
						
							|  |  |  |         || !route_table_fallback_lookup(ip6_dst, output_bridge, gw6)) { | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (netdev_get_in4_by_name(output_bridge, (struct in_addr *)&src)) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (src6) { | 
					
						
							|  |  |  |         in6_addr_set_mapped_ipv4(src6, src); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | bool | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  | ovs_router_lookup(uint32_t mark, const struct in6_addr *ip6_dst, | 
					
						
							|  |  |  |                   char output_bridge[], | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |                   struct in6_addr *src, struct in6_addr *gw) | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | { | 
					
						
							|  |  |  |     const struct cls_rule *cr; | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     struct flow flow = {.ipv6_dst = *ip6_dst, .pkt_mark = mark}; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 11:03:47 +08:00
										 |  |  |     if (src && ipv6_addr_is_set(src)) { | 
					
						
							|  |  |  |         const struct cls_rule *cr_src; | 
					
						
							|  |  |  |         struct flow flow_src = {.ipv6_dst = *src, .pkt_mark = mark}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cr_src = classifier_lookup(&cls, OVS_VERSION_MAX, &flow_src, NULL); | 
					
						
							|  |  |  |         if (cr_src) { | 
					
						
							|  |  |  |             struct ovs_router_entry *p_src = ovs_router_entry_cast(cr_src); | 
					
						
							|  |  |  |             if (!p_src->local) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-29 16:52:01 -07:00
										 |  |  |     cr = classifier_lookup(&cls, OVS_VERSION_MAX, &flow, NULL); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     if (cr) { | 
					
						
							|  |  |  |         struct ovs_router_entry *p = ovs_router_entry_cast(cr); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-20 12:32:08 -08:00
										 |  |  |         ovs_strlcpy(output_bridge, p->output_bridge, IFNAMSIZ); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |         *gw = p->gw; | 
					
						
							| 
									
										
										
										
											2018-04-18 11:03:47 +08:00
										 |  |  |         if (src && !ipv6_addr_is_set(src)) { | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |             *src = p->src_addr; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |     return ovs_router_lookup_fallback(ip6_dst, output_bridge, src, gw); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | rt_entry_free(struct ovs_router_entry *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     cls_rule_destroy(&p->cr); | 
					
						
							|  |  |  |     free(p); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  | static void rt_init_match(struct match *match, uint32_t mark, | 
					
						
							|  |  |  |                           const struct in6_addr *ip6_dst, | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |                           uint8_t plen) | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     struct in6_addr dst; | 
					
						
							|  |  |  |     struct in6_addr mask; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     mask = ipv6_create_mask(plen); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     dst = ipv6_addr_bitand(ip6_dst, &mask); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     memset(match, 0, sizeof *match); | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     match->flow.ipv6_dst = dst; | 
					
						
							|  |  |  |     match->wc.masks.ipv6_dst = mask; | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     match->wc.masks.pkt_mark = UINT32_MAX; | 
					
						
							|  |  |  |     match->flow.pkt_mark = mark; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  | static int | 
					
						
							|  |  |  | get_src_addr(const struct in6_addr *ip6_dst, | 
					
						
							|  |  |  |              const char output_bridge[], struct in6_addr *psrc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct in6_addr *mask, *addr6; | 
					
						
							|  |  |  |     int err, n_in6, i, max_plen = -1; | 
					
						
							|  |  |  |     struct netdev *dev; | 
					
						
							| 
									
										
										
										
											2016-07-24 13:07:26 -03:00
										 |  |  |     bool is_ipv4; | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     err = netdev_open(output_bridge, NULL, &dev); | 
					
						
							|  |  |  |     if (err) { | 
					
						
							|  |  |  |         return err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     err = netdev_get_addr_list(dev, &addr6, &mask, &n_in6); | 
					
						
							|  |  |  |     if (err) { | 
					
						
							|  |  |  |         goto out; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 13:07:26 -03:00
										 |  |  |     is_ipv4 = IN6_IS_ADDR_V4MAPPED(ip6_dst); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |     for (i = 0; i < n_in6; i++) { | 
					
						
							|  |  |  |         struct in6_addr a1, a2; | 
					
						
							|  |  |  |         int mask_bits; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 13:07:26 -03:00
										 |  |  |         if (is_ipv4 && !IN6_IS_ADDR_V4MAPPED(&addr6[i])) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |         a1 = ipv6_addr_bitand(ip6_dst, &mask[i]); | 
					
						
							|  |  |  |         a2 = ipv6_addr_bitand(&addr6[i], &mask[i]); | 
					
						
							|  |  |  |         mask_bits = bitmap_count1(ALIGNED_CAST(const unsigned long *, &mask[i]), 128); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!memcmp(&a1, &a2, sizeof (a1)) && mask_bits > max_plen) { | 
					
						
							|  |  |  |             *psrc = addr6[i]; | 
					
						
							|  |  |  |             max_plen = mask_bits; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (max_plen == -1) { | 
					
						
							|  |  |  |         err = ENOENT; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  |     free(addr6); | 
					
						
							|  |  |  |     free(mask); | 
					
						
							|  |  |  |     netdev_close(dev); | 
					
						
							|  |  |  |     return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2018-04-18 11:03:47 +08:00
										 |  |  | ovs_router_insert__(uint32_t mark, uint8_t priority, bool local, | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |                     const struct in6_addr *ip6_dst, | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |                     uint8_t plen, const char output_bridge[], | 
					
						
							|  |  |  |                     const struct in6_addr *gw) | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | { | 
					
						
							|  |  |  |     const struct cls_rule *cr; | 
					
						
							|  |  |  |     struct ovs_router_entry *p; | 
					
						
							|  |  |  |     struct match match; | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |     int err; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     rt_init_match(&match, mark, ip6_dst, plen); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     p = xzalloc(sizeof *p); | 
					
						
							| 
									
										
										
										
											2015-02-20 12:32:08 -08:00
										 |  |  |     ovs_strlcpy(p->output_bridge, output_bridge, sizeof p->output_bridge); | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     if (ipv6_addr_is_set(gw)) { | 
					
						
							|  |  |  |         p->gw = *gw; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     p->mark = mark; | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     p->nw_addr = match.flow.ipv6_dst; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     p->plen = plen; | 
					
						
							| 
									
										
										
										
											2018-04-18 11:03:47 +08:00
										 |  |  |     p->local = local; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     p->priority = priority; | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |     err = get_src_addr(ip6_dst, output_bridge, &p->src_addr); | 
					
						
							| 
									
										
										
										
											2016-11-15 01:49:47 -08:00
										 |  |  |     if (err && ipv6_addr_is_set(gw)) { | 
					
						
							|  |  |  |         err = get_src_addr(gw, output_bridge, &p->src_addr); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |     if (err) { | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |         struct ds ds = DS_EMPTY_INITIALIZER; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ipv6_format_mapped(ip6_dst, &ds); | 
					
						
							|  |  |  |         VLOG_DBG_RL(&rl, "src addr not available for route %s", ds_cstr(&ds)); | 
					
						
							| 
									
										
										
										
											2016-03-31 09:56:25 -07:00
										 |  |  |         free(p); | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |         ds_destroy(&ds); | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |         return err; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-06-09 17:00:00 -07:00
										 |  |  |     /* Longest prefix matches first. */ | 
					
						
							| 
									
										
										
										
											2015-07-06 11:45:54 -07:00
										 |  |  |     cls_rule_init(&p->cr, &match, priority); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-14 15:58:09 -08:00
										 |  |  |     ovs_mutex_lock(&mutex); | 
					
						
							| 
									
										
										
										
											2016-07-29 16:52:01 -07:00
										 |  |  |     cr = classifier_replace(&cls, &p->cr, OVS_VERSION_MIN, NULL, 0); | 
					
						
							| 
									
										
										
										
											2014-11-14 15:58:09 -08:00
										 |  |  |     ovs_mutex_unlock(&mutex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     if (cr) { | 
					
						
							|  |  |  |         /* An old rule with the same match was displaced. */ | 
					
						
							|  |  |  |         ovsrcu_postpone(rt_entry_free, ovs_router_entry_cast(cr)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-09-03 00:42:34 -07:00
										 |  |  |     tnl_port_map_insert_ipdev(output_bridge); | 
					
						
							| 
									
										
										
										
											2014-11-11 11:53:47 -08:00
										 |  |  |     seq_change(tnl_conf_seq); | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  | ovs_router_insert(uint32_t mark, const struct in6_addr *ip_dst, uint8_t plen, | 
					
						
							| 
									
										
										
										
											2018-04-18 11:03:47 +08:00
										 |  |  |                   bool local, const char output_bridge[],  | 
					
						
							|  |  |  |                   const struct in6_addr *gw) | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-31 17:12:55 -07:00
										 |  |  |     if (use_system_routing_table) { | 
					
						
							| 
									
										
										
										
											2018-04-18 11:03:47 +08:00
										 |  |  |         uint8_t priority = local ? plen + 64 : plen; | 
					
						
							|  |  |  |         ovs_router_insert__(mark, priority, local, ip_dst, plen, output_bridge, gw); | 
					
						
							| 
									
										
										
										
											2018-03-31 17:12:55 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-30 13:00:31 -08:00
										 |  |  | static void | 
					
						
							|  |  |  | rt_entry_delete__(const struct cls_rule *cr) | 
					
						
							| 
									
										
										
										
											2015-09-03 00:42:34 -07:00
										 |  |  | { | 
					
						
							|  |  |  |     struct ovs_router_entry *p = ovs_router_entry_cast(cr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tnl_port_map_delete_ipdev(p->output_bridge); | 
					
						
							| 
									
										
										
										
											2018-01-30 13:00:31 -08:00
										 |  |  |     classifier_remove_assert(&cls, cr); | 
					
						
							|  |  |  |     ovsrcu_postpone(rt_entry_free, ovs_router_entry_cast(cr)); | 
					
						
							| 
									
										
										
										
											2015-09-03 00:42:34 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | static bool | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  | rt_entry_delete(uint32_t mark, uint8_t priority, | 
					
						
							|  |  |  |                 const struct in6_addr *ip6_dst, uint8_t plen) | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-11-06 14:55:29 -08:00
										 |  |  |     const struct cls_rule *cr; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     struct cls_rule rule; | 
					
						
							|  |  |  |     struct match match; | 
					
						
							| 
									
										
										
										
											2015-09-03 00:42:34 -07:00
										 |  |  |     bool res = false; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     rt_init_match(&match, mark, ip6_dst, plen); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 11:45:54 -07:00
										 |  |  |     cls_rule_init(&rule, &match, priority); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Find the exact rule. */ | 
					
						
							| 
									
										
										
										
											2016-07-29 16:52:01 -07:00
										 |  |  |     cr = classifier_find_rule_exactly(&cls, &rule, OVS_VERSION_MAX); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     if (cr) { | 
					
						
							| 
									
										
										
										
											2014-11-14 15:58:09 -08:00
										 |  |  |         ovs_mutex_lock(&mutex); | 
					
						
							| 
									
										
										
										
											2018-01-30 13:00:31 -08:00
										 |  |  |         rt_entry_delete__(cr); | 
					
						
							| 
									
										
										
										
											2014-11-14 15:58:09 -08:00
										 |  |  |         ovs_mutex_unlock(&mutex); | 
					
						
							| 
									
										
										
										
											2018-01-30 13:00:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         res = true; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-08 07:03:53 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cls_rule_destroy(&rule); | 
					
						
							| 
									
										
										
										
											2015-09-03 00:42:34 -07:00
										 |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  | static bool | 
					
						
							|  |  |  | scan_ipv6_route(const char *s, struct in6_addr *addr, unsigned int *plen) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-12-15 18:04:20 -08:00
										 |  |  |     char *error = ipv6_parse_cidr(s, addr, plen); | 
					
						
							| 
									
										
										
										
											2015-11-10 15:45:03 -08:00
										 |  |  |     if (error) { | 
					
						
							|  |  |  |         free(error); | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-11-10 15:45:03 -08:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | static bool | 
					
						
							|  |  |  | scan_ipv4_route(const char *s, ovs_be32 *addr, unsigned int *plen) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-12-15 18:04:20 -08:00
										 |  |  |     char *error = ip_parse_cidr(s, addr, plen); | 
					
						
							|  |  |  |     if (error) { | 
					
						
							|  |  |  |         free(error); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-12-15 18:04:20 -08:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | ovs_router_add(struct unixctl_conn *conn, int argc, | 
					
						
							|  |  |  |               const char *argv[], void *aux OVS_UNUSED) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     struct in6_addr gw6 = in6addr_any; | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     struct in6_addr ip6; | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     uint32_t mark = 0; | 
					
						
							|  |  |  |     unsigned int plen; | 
					
						
							|  |  |  |     ovs_be32 ip; | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |     int err; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (scan_ipv4_route(argv[1], &ip, &plen)) { | 
					
						
							| 
									
										
										
										
											2015-12-15 18:04:20 -08:00
										 |  |  |         ovs_be32 gw = 0; | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (argc > 3) { | 
					
						
							|  |  |  |             if (!ovs_scan(argv[3], "pkt_mark=%"SCNi32, &mark) && | 
					
						
							|  |  |  |                 !ip_parse(argv[3], &gw)) { | 
					
						
							|  |  |  |                 unixctl_command_reply_error(conn, "Invalid pkt_mark or gateway"); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |         in6_addr_set_mapped_ipv4(&ip6, ip); | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |         if (gw) { | 
					
						
							|  |  |  |             in6_addr_set_mapped_ipv4(&gw6, gw); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |         plen += 96; | 
					
						
							|  |  |  |     } else if (scan_ipv6_route(argv[1], &ip6, &plen)) { | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |         if (argc > 3) { | 
					
						
							|  |  |  |             if (!ovs_scan(argv[3], "pkt_mark=%"SCNi32, &mark) && | 
					
						
							|  |  |  |                 !ipv6_parse(argv[3], &gw6)) { | 
					
						
							|  |  |  |                 unixctl_command_reply_error(conn, "Invalid pkt_mark or IPv6 gateway"); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2015-11-23 20:49:35 -08:00
										 |  |  |         unixctl_command_reply_error(conn, "Invalid parameters"); | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     if (argc > 4) { | 
					
						
							|  |  |  |         if (!ovs_scan(argv[4], "pkt_mark=%"SCNi32, &mark)) { | 
					
						
							|  |  |  |             unixctl_command_reply_error(conn, "Invalid pkt_mark"); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 11:03:47 +08:00
										 |  |  |     err = ovs_router_insert__(mark, plen + 32, false, &ip6, plen, argv[2], &gw6); | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |     if (err) { | 
					
						
							| 
									
										
										
										
											2016-11-15 01:49:46 -08:00
										 |  |  |         unixctl_command_reply_error(conn, "Error while inserting route."); | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         unixctl_command_reply(conn, "OK"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | ovs_router_del(struct unixctl_conn *conn, int argc OVS_UNUSED, | 
					
						
							|  |  |  |               const char *argv[], void *aux OVS_UNUSED) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     struct in6_addr ip6; | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     uint32_t mark = 0; | 
					
						
							|  |  |  |     unsigned int plen; | 
					
						
							|  |  |  |     ovs_be32 ip; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (scan_ipv4_route(argv[1], &ip, &plen)) { | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |         in6_addr_set_mapped_ipv4(&ip6, ip); | 
					
						
							|  |  |  |         plen += 96; | 
					
						
							|  |  |  |     } else if (!scan_ipv6_route(argv[1], &ip6, &plen)) { | 
					
						
							| 
									
										
										
										
											2015-11-23 20:49:35 -08:00
										 |  |  |         unixctl_command_reply_error(conn, "Invalid parameters"); | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     if (argc > 2) { | 
					
						
							|  |  |  |         if (!ovs_scan(argv[2], "pkt_mark=%"SCNi32, &mark)) { | 
					
						
							|  |  |  |             unixctl_command_reply_error(conn, "Invalid pkt_mark"); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (rt_entry_delete(mark, plen + 32, &ip6, plen)) { | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |         unixctl_command_reply(conn, "OK"); | 
					
						
							|  |  |  |         seq_change(tnl_conf_seq); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2015-11-23 20:49:35 -08:00
										 |  |  |         unixctl_command_reply_error(conn, "Not found"); | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | ovs_router_show(struct unixctl_conn *conn, int argc OVS_UNUSED, | 
					
						
							|  |  |  |                const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct ovs_router_entry *rt; | 
					
						
							|  |  |  |     struct ds ds = DS_EMPTY_INITIALIZER; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ds_put_format(&ds, "Route Table:\n"); | 
					
						
							|  |  |  |     CLS_FOR_EACH(rt, cr, &cls) { | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |         uint8_t plen; | 
					
						
							| 
									
										
										
										
											2018-04-18 11:03:47 +08:00
										 |  |  |         if (rt->priority == rt->plen || rt->local) { | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |             ds_put_format(&ds, "Cached: "); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ds_put_format(&ds, "User: "); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-10-25 13:19:22 -07:00
										 |  |  |         ipv6_format_mapped(&rt->nw_addr, &ds); | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |         plen = rt->plen; | 
					
						
							|  |  |  |         if (IN6_IS_ADDR_V4MAPPED(&rt->nw_addr)) { | 
					
						
							|  |  |  |             plen -= 96; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-03-17 13:38:55 -07:00
										 |  |  |         ds_put_format(&ds, "/%"PRIu8, plen); | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |         if (rt->mark) { | 
					
						
							|  |  |  |             ds_put_format(&ds, " MARK %"PRIu32, rt->mark); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ds_put_format(&ds, " dev %s", rt->output_bridge); | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |         if (ipv6_addr_is_set(&rt->gw)) { | 
					
						
							|  |  |  |             ds_put_format(&ds, " GW "); | 
					
						
							| 
									
										
										
										
											2015-10-25 13:19:22 -07:00
										 |  |  |             ipv6_format_mapped(&rt->gw, &ds); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |         ds_put_format(&ds, " SRC "); | 
					
						
							|  |  |  |         ipv6_format_mapped(&rt->src_addr, &ds); | 
					
						
							| 
									
										
										
										
											2018-04-18 11:03:47 +08:00
										 |  |  |         if (rt->local) { | 
					
						
							|  |  |  |             ds_put_format(&ds, " local"); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |         ds_put_format(&ds, "\n"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     unixctl_command_reply(conn, ds_cstr(&ds)); | 
					
						
							|  |  |  |     ds_destroy(&ds); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-17 15:05:54 +09:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  | ovs_router_lookup_cmd(struct unixctl_conn *conn, int argc, | 
					
						
							| 
									
										
										
										
											2014-11-17 15:05:54 +09:00
										 |  |  |                       const char *argv[], void *aux OVS_UNUSED) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-04-18 11:03:47 +08:00
										 |  |  |     struct in6_addr gw, src = in6addr_any; | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     char iface[IFNAMSIZ]; | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     struct in6_addr ip6; | 
					
						
							| 
									
										
										
										
											2014-11-17 15:05:54 +09:00
										 |  |  |     unsigned int plen; | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     uint32_t mark = 0; | 
					
						
							|  |  |  |     ovs_be32 ip; | 
					
						
							| 
									
										
										
										
											2014-11-17 15:05:54 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (scan_ipv4_route(argv[1], &ip, &plen) && plen == 32) { | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |         in6_addr_set_mapped_ipv4(&ip6, ip); | 
					
						
							|  |  |  |     } else if (!(scan_ipv6_route(argv[1], &ip6, &plen) && plen == 128)) { | 
					
						
							| 
									
										
										
										
											2015-11-23 20:49:35 -08:00
										 |  |  |         unixctl_command_reply_error(conn, "Invalid parameters"); | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  |     if (argc > 2) { | 
					
						
							|  |  |  |         if (!ovs_scan(argv[2], "pkt_mark=%"SCNi32, &mark)) { | 
					
						
							|  |  |  |             unixctl_command_reply_error(conn, "Invalid pkt_mark"); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ovs_router_lookup(mark, &ip6, iface, &src, &gw)) { | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |         struct ds ds = DS_EMPTY_INITIALIZER; | 
					
						
							| 
									
										
										
										
											2016-12-28 11:41:25 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |         ds_put_format(&ds, "src "); | 
					
						
							|  |  |  |         ipv6_format_mapped(&src, &ds); | 
					
						
							| 
									
										
										
										
											2016-11-24 16:38:39 -02:00
										 |  |  |         ds_put_format(&ds, "\ngateway "); | 
					
						
							| 
									
										
										
										
											2016-03-24 09:30:57 -07:00
										 |  |  |         ipv6_format_mapped(&gw, &ds); | 
					
						
							| 
									
										
										
										
											2015-09-29 19:10:56 -03:00
										 |  |  |         ds_put_format(&ds, "\ndev %s\n", iface); | 
					
						
							|  |  |  |         unixctl_command_reply(conn, ds_cstr(&ds)); | 
					
						
							|  |  |  |         ds_destroy(&ds); | 
					
						
							| 
									
										
										
										
											2014-11-17 15:05:54 +09:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2015-11-23 20:49:35 -08:00
										 |  |  |         unixctl_command_reply_error(conn, "Not found"); | 
					
						
							| 
									
										
										
										
											2014-11-17 15:05:54 +09:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | void | 
					
						
							|  |  |  | ovs_router_flush(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct ovs_router_entry *rt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-13 11:54:31 -08:00
										 |  |  |     ovs_mutex_lock(&mutex); | 
					
						
							|  |  |  |     classifier_defer(&cls); | 
					
						
							| 
									
										
										
										
											2014-11-13 11:54:31 -08:00
										 |  |  |     CLS_FOR_EACH(rt, cr, &cls) { | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |         if (rt->priority == rt->plen) { | 
					
						
							| 
									
										
										
										
											2018-01-30 13:00:31 -08:00
										 |  |  |             rt_entry_delete__(&rt->cr); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-11-13 11:54:31 -08:00
										 |  |  |     classifier_publish(&cls); | 
					
						
							|  |  |  |     ovs_mutex_unlock(&mutex); | 
					
						
							| 
									
										
										
										
											2014-11-11 11:53:47 -08:00
										 |  |  |     seq_change(tnl_conf_seq); | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 16:40:21 -03:00
										 |  |  | static void | 
					
						
							|  |  |  | ovs_router_flush_handler(void *aux OVS_UNUSED) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ovs_router_flush(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2014-11-19 22:12:21 -08:00
										 |  |  | ovs_router_init(void) | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-05-29 16:40:21 -03:00
										 |  |  |     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ovsthread_once_start(&once)) { | 
					
						
							|  |  |  |         fatal_signal_add_hook(ovs_router_flush_handler, NULL, NULL, true); | 
					
						
							|  |  |  |         classifier_init(&cls, NULL); | 
					
						
							|  |  |  |         unixctl_command_register("ovs/route/add", | 
					
						
							|  |  |  |                                  "ip_addr/prefix_len out_br_name [gw] " | 
					
						
							|  |  |  |                                  "[pkt_mark=mark]", | 
					
						
							|  |  |  |                                  2, 4, ovs_router_add, NULL); | 
					
						
							|  |  |  |         unixctl_command_register("ovs/route/show", "", 0, 0, | 
					
						
							|  |  |  |                                  ovs_router_show, NULL); | 
					
						
							|  |  |  |         unixctl_command_register("ovs/route/del", "ip_addr/prefix_len " | 
					
						
							|  |  |  |                                  "[pkt_mark=mark]", 1, 2, ovs_router_del, | 
					
						
							|  |  |  |                                  NULL); | 
					
						
							|  |  |  |         unixctl_command_register("ovs/route/lookup", "ip_addr " | 
					
						
							|  |  |  |                                  "[pkt_mark=mark]", 1, 2, | 
					
						
							|  |  |  |                                  ovs_router_lookup_cmd, NULL); | 
					
						
							|  |  |  |         ovsthread_once_done(&once); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-10-16 11:38:12 -07:00
										 |  |  | } |