]> git.proxmox.com Git - mirror_ovs.git/blob - ofproto/ofproto-dpif-xlate-cache.c
ofproto-dpif: Fix for recirc issue with mpls traffic with dp_hash
[mirror_ovs.git] / ofproto / ofproto-dpif-xlate-cache.c
1 /* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, 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 #include <config.h>
16
17 #include "ofproto/ofproto-dpif-xlate-cache.h"
18
19 #include <sys/types.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #include <errno.h>
23 #include <net/if.h>
24 #include <sys/socket.h>
25
26 #include "bfd.h"
27 #include "bitmap.h"
28 #include "bond.h"
29 #include "bundle.h"
30 #include "byte-order.h"
31 #include "connmgr.h"
32 #include "coverage.h"
33 #include "dp-packet.h"
34 #include "dpif.h"
35 #include "learn.h"
36 #include "mac-learning.h"
37 #include "netdev-vport.h"
38 #include "ofproto/ofproto-dpif-mirror.h"
39 #include "ofproto/ofproto-dpif-xlate.h"
40 #include "ofproto/ofproto-dpif.h"
41 #include "ofproto/ofproto-provider.h"
42 #include "openvswitch/dynamic-string.h"
43 #include "openvswitch/vlog.h"
44 #include "ovs-router.h"
45 #include "packets.h"
46 #include "tnl-neigh-cache.h"
47 #include "util.h"
48
49 VLOG_DEFINE_THIS_MODULE(ofproto_xlate_cache);
50
51 void
52 xlate_cache_init(struct xlate_cache *xcache)
53 {
54 ofpbuf_init(&xcache->entries, 120);
55 }
56
57 struct xlate_cache *
58 xlate_cache_new(void)
59 {
60 struct xlate_cache *xcache = xmalloc(sizeof *xcache);
61 xlate_cache_init(xcache);
62 return xcache;
63 }
64
65 struct xc_entry *
66 xlate_cache_add_entry(struct xlate_cache *xcache, enum xc_type type)
67 {
68 struct xc_entry *entry;
69
70 entry = ofpbuf_put_zeros(&xcache->entries, sizeof *entry);
71 entry->type = type;
72
73 return entry;
74 }
75
76 static void
77 xlate_cache_netdev(struct xc_entry *entry, const struct dpif_flow_stats *stats)
78 {
79 if (entry->dev.tx) {
80 netdev_vport_inc_tx(entry->dev.tx, stats);
81 }
82 if (entry->dev.rx) {
83 netdev_vport_inc_rx(entry->dev.rx, stats);
84 }
85 if (entry->dev.bfd) {
86 bfd_account_rx(entry->dev.bfd, stats);
87 }
88 }
89
90 /* Push stats and perform side effects of flow translation. */
91 void
92 xlate_push_stats_entry(struct xc_entry *entry,
93 struct dpif_flow_stats *stats)
94 {
95 struct eth_addr dmac;
96
97 switch (entry->type) {
98 case XC_TABLE:
99 ofproto_dpif_credit_table_stats(entry->table.ofproto,
100 entry->table.id,
101 entry->table.match
102 ? stats->n_packets : 0,
103 entry->table.match
104 ? 0 : stats->n_packets);
105 break;
106 case XC_RULE:
107 rule_dpif_credit_stats(entry->rule, stats);
108 break;
109 case XC_BOND:
110 bond_account(entry->bond.bond, entry->bond.flow,
111 entry->bond.vid, stats->n_bytes);
112 break;
113 case XC_NETDEV:
114 xlate_cache_netdev(entry, stats);
115 break;
116 case XC_NETFLOW:
117 netflow_flow_update(entry->nf.netflow, entry->nf.flow,
118 entry->nf.iface, stats);
119 break;
120 case XC_MIRROR:
121 mirror_update_stats(entry->mirror.mbridge,
122 entry->mirror.mirrors,
123 stats->n_packets, stats->n_bytes);
124 break;
125 case XC_LEARN: {
126 enum ofperr error;
127 error = ofproto_flow_mod_learn(entry->learn.ofm, true,
128 entry->learn.limit, NULL);
129 if (error) {
130 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
131 VLOG_WARN_RL(&rl, "xcache LEARN action execution failed.");
132 }
133 break;
134 }
135 case XC_NORMAL:
136 xlate_mac_learning_update(entry->normal.ofproto,
137 entry->normal.in_port,
138 entry->normal.dl_src,
139 entry->normal.vlan,
140 entry->normal.is_gratuitous_arp);
141 break;
142 case XC_FIN_TIMEOUT:
143 if (stats->tcp_flags & (TCP_FIN | TCP_RST)) {
144 ofproto_rule_reduce_timeouts(&entry->fin.rule->up, entry->fin.idle,
145 entry->fin.hard);
146 }
147 break;
148 case XC_GROUP:
149 group_dpif_credit_stats(entry->group.group, entry->group.bucket,
150 stats);
151 break;
152 case XC_TNL_NEIGH:
153 /* Lookup neighbor to avoid timeout. */
154 tnl_neigh_lookup(entry->tnl_neigh_cache.br_name,
155 &entry->tnl_neigh_cache.d_ipv6, &dmac);
156 break;
157 case XC_TUNNEL_HEADER:
158 if (entry->tunnel_hdr.operation == ADD) {
159 stats->n_bytes += stats->n_packets * entry->tunnel_hdr.hdr_size;
160 } else {
161 stats->n_bytes -= stats->n_packets * entry->tunnel_hdr.hdr_size;
162 }
163
164 break;
165 default:
166 OVS_NOT_REACHED();
167 }
168 }
169
170 void
171 xlate_push_stats(struct xlate_cache *xcache,
172 struct dpif_flow_stats *stats)
173 {
174 if (!stats->n_packets) {
175 return;
176 }
177
178 struct xc_entry *entry;
179 struct ofpbuf entries = xcache->entries;
180 XC_ENTRY_FOR_EACH (entry, &entries) {
181 xlate_push_stats_entry(entry, stats);
182 }
183 }
184
185 static void
186 xlate_dev_unref(struct xc_entry *entry)
187 {
188 if (entry->dev.tx) {
189 netdev_close(entry->dev.tx);
190 }
191 if (entry->dev.rx) {
192 netdev_close(entry->dev.rx);
193 }
194 if (entry->dev.bfd) {
195 bfd_unref(entry->dev.bfd);
196 }
197 }
198
199 static void
200 xlate_cache_clear_netflow(struct netflow *netflow, struct flow *flow)
201 {
202 netflow_flow_clear(netflow, flow);
203 netflow_unref(netflow);
204 free(flow);
205 }
206
207 void
208 xlate_cache_clear_entry(struct xc_entry *entry)
209 {
210 switch (entry->type) {
211 case XC_TABLE:
212 break;
213 case XC_RULE:
214 ofproto_rule_unref(&entry->rule->up);
215 break;
216 case XC_BOND:
217 free(entry->bond.flow);
218 bond_unref(entry->bond.bond);
219 break;
220 case XC_NETDEV:
221 xlate_dev_unref(entry);
222 break;
223 case XC_NETFLOW:
224 xlate_cache_clear_netflow(entry->nf.netflow, entry->nf.flow);
225 break;
226 case XC_MIRROR:
227 mbridge_unref(entry->mirror.mbridge);
228 break;
229 case XC_LEARN:
230 ofproto_flow_mod_uninit(entry->learn.ofm);
231 free(entry->learn.ofm);
232 break;
233 case XC_NORMAL:
234 break;
235 case XC_FIN_TIMEOUT:
236 /* 'u.fin.rule' is always already held as a XC_RULE, which
237 * has already released it's reference above. */
238 break;
239 case XC_GROUP:
240 ofproto_group_unref(&entry->group.group->up);
241 break;
242 case XC_TNL_NEIGH:
243 break;
244 case XC_TUNNEL_HEADER:
245 break;
246 default:
247 OVS_NOT_REACHED();
248 }
249 }
250
251 void
252 xlate_cache_clear(struct xlate_cache *xcache)
253 {
254 if (!xcache) {
255 return;
256 }
257
258 struct xc_entry *entry;
259 struct ofpbuf entries = xcache->entries;
260 XC_ENTRY_FOR_EACH (entry, &entries) {
261 xlate_cache_clear_entry(entry);
262 }
263
264 ofpbuf_clear(&xcache->entries);
265 }
266
267 void
268 xlate_cache_uninit(struct xlate_cache *xcache)
269 {
270 if (!xcache) {
271 return;
272 }
273 xlate_cache_clear(xcache);
274 ofpbuf_uninit(&xcache->entries);
275 }
276
277 void
278 xlate_cache_delete(struct xlate_cache *xcache)
279 {
280 xlate_cache_uninit(xcache);
281 free(xcache);
282 }
283
284 /* Append all the entries in src into dst and remove them from src.
285 * The caller must own both xc-caches to use this function.
286 * The 'src' entries are not freed in this function as its owned by caller.
287 */
288 void
289 xlate_cache_steal_entries(struct xlate_cache *dst, struct xlate_cache *src)
290 {
291 if (!dst || !src) {
292 return;
293 }
294 struct ofpbuf *src_entries = &src->entries;
295 struct ofpbuf *dst_entries = &dst->entries;
296 void *p;
297
298 p = ofpbuf_put_uninit(dst_entries, src_entries->size);
299 memcpy(p, src_entries->data, src_entries->size);
300 ofpbuf_clear(src_entries);
301 }