]>
Commit | Line | Data |
---|---|---|
901a517e JR |
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 | ||
b2befd5b BP |
19 | #include <sys/types.h> |
20 | #include <netinet/in.h> | |
901a517e | 21 | #include <arpa/inet.h> |
1f4a8933 | 22 | #include <errno.h> |
901a517e | 23 | #include <net/if.h> |
1f4a8933 | 24 | #include <sys/socket.h> |
901a517e JR |
25 | |
26 | #include "bfd.h" | |
27 | #include "bitmap.h" | |
28 | #include "bond.h" | |
29 | #include "bundle.h" | |
30 | #include "byte-order.h" | |
df70a773 | 31 | #include "connmgr.h" |
901a517e JR |
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" | |
901a517e | 39 | #include "ofproto/ofproto-dpif-xlate.h" |
1f4a8933 | 40 | #include "ofproto/ofproto-dpif.h" |
901a517e JR |
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 | ||
1f4a8933 JR |
51 | void |
52 | xlate_cache_init(struct xlate_cache *xcache) | |
53 | { | |
54 | ofpbuf_init(&xcache->entries, 120); | |
55 | } | |
56 | ||
901a517e JR |
57 | struct xlate_cache * |
58 | xlate_cache_new(void) | |
59 | { | |
60 | struct xlate_cache *xcache = xmalloc(sizeof *xcache); | |
1f4a8933 | 61 | xlate_cache_init(xcache); |
901a517e JR |
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, | |
7c12dfc5 | 93 | struct dpif_flow_stats *stats) |
901a517e JR |
94 | { |
95 | struct eth_addr dmac; | |
96 | ||
97 | switch (entry->type) { | |
a027899e JR |
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; | |
901a517e JR |
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; | |
2c7ee524 JR |
125 | case XC_LEARN: { |
126 | enum ofperr error; | |
4c71600d DDP |
127 | error = ofproto_flow_mod_learn(entry->learn.ofm, true, |
128 | entry->learn.limit, NULL); | |
2c7ee524 JR |
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 | } | |
901a517e | 133 | break; |
2c7ee524 | 134 | } |
901a517e JR |
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)) { | |
07a3cd5c BP |
144 | ofproto_rule_reduce_timeouts(&entry->fin.rule->up, entry->fin.idle, |
145 | entry->fin.hard); | |
901a517e JR |
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; | |
7c12dfc5 SC |
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 | ||
df70a773 | 164 | break; |
901a517e JR |
165 | default: |
166 | OVS_NOT_REACHED(); | |
167 | } | |
168 | } | |
169 | ||
170 | void | |
171 | xlate_push_stats(struct xlate_cache *xcache, | |
7c12dfc5 | 172 | struct dpif_flow_stats *stats) |
901a517e JR |
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) { | |
a027899e JR |
211 | case XC_TABLE: |
212 | break; | |
901a517e | 213 | case XC_RULE: |
07a3cd5c | 214 | ofproto_rule_unref(&entry->rule->up); |
901a517e JR |
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: | |
2c7ee524 JR |
230 | ofproto_flow_mod_uninit(entry->learn.ofm); |
231 | free(entry->learn.ofm); | |
901a517e JR |
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: | |
07a3cd5c | 240 | ofproto_group_unref(&entry->group.group->up); |
901a517e JR |
241 | break; |
242 | case XC_TNL_NEIGH: | |
243 | break; | |
7c12dfc5 SC |
244 | case XC_TUNNEL_HEADER: |
245 | break; | |
901a517e JR |
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 | |
1f4a8933 | 268 | xlate_cache_uninit(struct xlate_cache *xcache) |
901a517e | 269 | { |
edc0e86d JP |
270 | if (!xcache) { |
271 | return; | |
272 | } | |
901a517e JR |
273 | xlate_cache_clear(xcache); |
274 | ofpbuf_uninit(&xcache->entries); | |
1f4a8933 JR |
275 | } |
276 | ||
277 | void | |
278 | xlate_cache_delete(struct xlate_cache *xcache) | |
279 | { | |
280 | xlate_cache_uninit(xcache); | |
901a517e JR |
281 | free(xcache); |
282 | } | |
7c12dfc5 SC |
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 | } |