]>
Commit | Line | Data |
---|---|---|
777af88d AC |
1 | /* |
2 | * Copyright (c) 2013, 2014 Alexandru Copot <alex.mihai.c@gmail.com>, with support from IXIA. | |
3 | * Copyright (c) 2013, 2014 Daniel Baluta <dbaluta@ixiacom.com> | |
51bb26fa | 4 | * Copyright (c) 2014, 2015, 2016 Nicira, Inc. |
777af88d AC |
5 | * |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
7 | * you may not use this file except in compliance with the License. | |
8 | * You may obtain a copy of the License at: | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, software | |
13 | * distributed under the License is distributed on an "AS IS" BASIS, | |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | * See the License for the specific language governing permissions and | |
16 | * limitations under the License. | |
17 | */ | |
18 | ||
19 | #include <config.h> | |
20 | ||
b598f214 | 21 | #include "bundles.h" |
777af88d AC |
22 | #include "coverage.h" |
23 | #include "fail-open.h" | |
24 | #include "in-band.h" | |
25 | #include "odp-util.h" | |
d271907f | 26 | #include "ofproto-provider.h" |
b598f214 | 27 | #include "openvswitch/ofp-actions.h" |
d271907f | 28 | #include "openvswitch/ofp-msgs.h" |
64c96779 | 29 | #include "openvswitch/ofpbuf.h" |
d271907f BW |
30 | #include "openvswitch/vconn.h" |
31 | #include "openvswitch/vlog.h" | |
777af88d | 32 | #include "pinsched.h" |
fd016ae3 | 33 | #include "openvswitch/poll-loop.h" |
dc02e1eb | 34 | #include "openvswitch/rconn.h" |
ee89ea7b | 35 | #include "openvswitch/shash.h" |
777af88d AC |
36 | #include "simap.h" |
37 | #include "stream.h" | |
38 | #include "timeval.h" | |
777af88d | 39 | |
777af88d AC |
40 | VLOG_DEFINE_THIS_MODULE(bundles); |
41 | ||
777af88d | 42 | static struct ofp_bundle * |
51bb26fa | 43 | ofp_bundle_create(uint32_t id, uint16_t flags, const struct ofp_header *oh) |
777af88d AC |
44 | { |
45 | struct ofp_bundle *bundle; | |
46 | ||
47 | bundle = xmalloc(sizeof(*bundle)); | |
48 | ||
51bb26fa | 49 | bundle->used = time_msec(); |
777af88d AC |
50 | bundle->id = id; |
51 | bundle->flags = flags; | |
ff09bc08 | 52 | bundle->state = BS_OPEN; |
52c57cbb | 53 | bundle->msg = xmemdup(oh, ntohs(oh->length)); |
777af88d | 54 | |
417e7e66 | 55 | ovs_list_init(&bundle->msg_list); |
777af88d AC |
56 | |
57 | return bundle; | |
58 | } | |
59 | ||
ff09bc08 | 60 | void |
0c78eebe | 61 | ofp_bundle_remove__(struct ofconn *ofconn, struct ofp_bundle *bundle) |
777af88d | 62 | { |
7ac27a04 | 63 | struct ofp_bundle_entry *msg; |
777af88d | 64 | |
7ac27a04 JR |
65 | LIST_FOR_EACH_POP (msg, node, &bundle->msg_list) { |
66 | ofp_bundle_entry_free(msg); | |
777af88d AC |
67 | } |
68 | ||
ff09bc08 | 69 | ofconn_remove_bundle(ofconn, bundle); |
52c57cbb | 70 | free(bundle->msg); |
7ac27a04 | 71 | free(bundle); |
777af88d AC |
72 | } |
73 | ||
777af88d | 74 | enum ofperr |
51bb26fa JR |
75 | ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags, |
76 | const struct ofp_header *oh) | |
777af88d | 77 | { |
777af88d AC |
78 | struct ofp_bundle *bundle; |
79 | ||
ff09bc08 | 80 | bundle = ofconn_get_bundle(ofconn, id); |
777af88d AC |
81 | |
82 | if (bundle) { | |
83 | VLOG_INFO("Bundle %x already exists.", id); | |
0c78eebe | 84 | ofp_bundle_remove__(ofconn, bundle); |
777af88d AC |
85 | |
86 | return OFPERR_OFPBFC_BAD_ID; | |
87 | } | |
88 | ||
51bb26fa | 89 | bundle = ofp_bundle_create(id, flags, oh); |
52c57cbb | 90 | ofconn_insert_bundle(ofconn, bundle); |
777af88d | 91 | |
52c57cbb | 92 | return 0; |
777af88d AC |
93 | } |
94 | ||
95 | enum ofperr | |
96 | ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags) | |
97 | { | |
777af88d AC |
98 | struct ofp_bundle *bundle; |
99 | ||
ff09bc08 | 100 | bundle = ofconn_get_bundle(ofconn, id); |
777af88d AC |
101 | |
102 | if (!bundle) { | |
103 | return OFPERR_OFPBFC_BAD_ID; | |
104 | } | |
105 | ||
106 | if (bundle->state == BS_CLOSED) { | |
0c78eebe | 107 | ofp_bundle_remove__(ofconn, bundle); |
777af88d AC |
108 | return OFPERR_OFPBFC_BUNDLE_CLOSED; |
109 | } | |
110 | ||
111 | if (bundle->flags != flags) { | |
0c78eebe | 112 | ofp_bundle_remove__(ofconn, bundle); |
777af88d AC |
113 | return OFPERR_OFPBFC_BAD_FLAGS; |
114 | } | |
115 | ||
51bb26fa | 116 | bundle->used = time_msec(); |
777af88d AC |
117 | bundle->state = BS_CLOSED; |
118 | return 0; | |
119 | } | |
120 | ||
777af88d AC |
121 | enum ofperr |
122 | ofp_bundle_discard(struct ofconn *ofconn, uint32_t id) | |
123 | { | |
777af88d AC |
124 | struct ofp_bundle *bundle; |
125 | ||
ff09bc08 | 126 | bundle = ofconn_get_bundle(ofconn, id); |
777af88d AC |
127 | |
128 | if (!bundle) { | |
129 | return OFPERR_OFPBFC_BAD_ID; | |
130 | } | |
131 | ||
0c78eebe | 132 | ofp_bundle_remove__(ofconn, bundle); |
777af88d AC |
133 | return 0; |
134 | } | |
135 | ||
136 | enum ofperr | |
7ac27a04 | 137 | ofp_bundle_add_message(struct ofconn *ofconn, uint32_t id, uint16_t flags, |
51bb26fa JR |
138 | struct ofp_bundle_entry *bmsg, |
139 | const struct ofp_header *oh) | |
777af88d | 140 | { |
777af88d | 141 | struct ofp_bundle *bundle; |
777af88d | 142 | |
ff09bc08 | 143 | bundle = ofconn_get_bundle(ofconn, id); |
777af88d AC |
144 | |
145 | if (!bundle) { | |
51bb26fa | 146 | bundle = ofp_bundle_create(id, flags, oh); |
52c57cbb | 147 | ofconn_insert_bundle(ofconn, bundle); |
7b334c5c | 148 | } else if (bundle->state == BS_CLOSED) { |
0c78eebe | 149 | ofp_bundle_remove__(ofconn, bundle); |
777af88d | 150 | return OFPERR_OFPBFC_BUNDLE_CLOSED; |
7ac27a04 | 151 | } else if (flags != bundle->flags) { |
0c78eebe | 152 | ofp_bundle_remove__(ofconn, bundle); |
7b334c5c | 153 | return OFPERR_OFPBFC_BAD_FLAGS; |
777af88d AC |
154 | } |
155 | ||
51bb26fa | 156 | bundle->used = time_msec(); |
417e7e66 | 157 | ovs_list_push_back(&bundle->msg_list, &bmsg->node); |
777af88d AC |
158 | return 0; |
159 | } |