datapath: remove rtnl_delete_link support for older Linux
[cascardo/ovs.git] / ofproto / bundles.c
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>
4  * Copyright (c) 2014, 2015 Nicira, Inc.
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
21 #include "bundles.h"
22 #include "coverage.h"
23 #include "fail-open.h"
24 #include "in-band.h"
25 #include "odp-util.h"
26 #include "ofproto-provider.h"
27 #include "openvswitch/ofp-actions.h"
28 #include "openvswitch/ofp-msgs.h"
29 #include "openvswitch/ofp-util.h"
30 #include "openvswitch/ofpbuf.h"
31 #include "openvswitch/vconn.h"
32 #include "openvswitch/vlog.h"
33 #include "pinsched.h"
34 #include "poll-loop.h"
35 #include "pktbuf.h"
36 #include "rconn.h"
37 #include "openvswitch/shash.h"
38 #include "simap.h"
39 #include "stream.h"
40 #include "timeval.h"
41
42 VLOG_DEFINE_THIS_MODULE(bundles);
43
44 static struct ofp_bundle *
45 ofp_bundle_create(uint32_t id, uint16_t flags)
46 {
47     struct ofp_bundle *bundle;
48
49     bundle = xmalloc(sizeof(*bundle));
50
51     bundle->id = id;
52     bundle->flags = flags;
53     bundle->state = BS_OPEN;
54
55     ovs_list_init(&bundle->msg_list);
56
57     return bundle;
58 }
59
60 void
61 ofp_bundle_remove__(struct ofconn *ofconn, struct ofp_bundle *bundle,
62                     bool success)
63 {
64     struct ofp_bundle_entry *msg;
65
66     LIST_FOR_EACH_POP (msg, node, &bundle->msg_list) {
67         if (success && msg->type == OFPTYPE_FLOW_MOD) {
68             /* Tell connmgr about successful flow mods. */
69             ofconn_report_flow_mod(ofconn, msg->ofm.fm.command);
70         }
71         ofp_bundle_entry_free(msg);
72     }
73
74     ofconn_remove_bundle(ofconn, bundle);
75     free(bundle);
76 }
77
78 enum ofperr
79 ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags)
80 {
81     struct ofp_bundle *bundle;
82     enum ofperr error;
83
84     bundle = ofconn_get_bundle(ofconn, id);
85
86     if (bundle) {
87         VLOG_INFO("Bundle %x already exists.", id);
88         ofp_bundle_remove__(ofconn, bundle, false);
89
90         return OFPERR_OFPBFC_BAD_ID;
91     }
92
93     bundle = ofp_bundle_create(id, flags);
94     error = ofconn_insert_bundle(ofconn, bundle);
95     if (error) {
96         free(bundle);
97     }
98
99     return error;
100 }
101
102 enum ofperr
103 ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags)
104 {
105     struct ofp_bundle *bundle;
106
107     bundle = ofconn_get_bundle(ofconn, id);
108
109     if (!bundle) {
110         return OFPERR_OFPBFC_BAD_ID;
111     }
112
113     if (bundle->state == BS_CLOSED) {
114         ofp_bundle_remove__(ofconn, bundle, false);
115         return OFPERR_OFPBFC_BUNDLE_CLOSED;
116     }
117
118     if (bundle->flags != flags) {
119         ofp_bundle_remove__(ofconn, bundle, false);
120         return OFPERR_OFPBFC_BAD_FLAGS;
121     }
122
123     bundle->state = BS_CLOSED;
124     return 0;
125 }
126
127 enum ofperr
128 ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
129 {
130     struct ofp_bundle *bundle;
131
132     bundle = ofconn_get_bundle(ofconn, id);
133
134     if (!bundle) {
135         return OFPERR_OFPBFC_BAD_ID;
136     }
137
138     ofp_bundle_remove__(ofconn, bundle, false);
139
140     return 0;
141 }
142
143 enum ofperr
144 ofp_bundle_add_message(struct ofconn *ofconn, uint32_t id, uint16_t flags,
145                        struct ofp_bundle_entry *bmsg)
146 {
147     struct ofp_bundle *bundle;
148
149     bundle = ofconn_get_bundle(ofconn, id);
150
151     if (!bundle) {
152         enum ofperr error;
153
154         bundle = ofp_bundle_create(id, flags);
155         error = ofconn_insert_bundle(ofconn, bundle);
156         if (error) {
157             free(bundle);
158             return error;
159         }
160     } else if (bundle->state == BS_CLOSED) {
161         ofp_bundle_remove__(ofconn, bundle, false);
162         return OFPERR_OFPBFC_BUNDLE_CLOSED;
163     } else if (flags != bundle->flags) {
164         ofp_bundle_remove__(ofconn, bundle, false);
165         return OFPERR_OFPBFC_BAD_FLAGS;
166     }
167
168     ovs_list_push_back(&bundle->msg_list, &bmsg->node);
169     return 0;
170 }