fix a header guard
[libof.git] / of10.c
blob0d9d48c73915f3cad15b248f2418c402d887b731
1 /*
2 * Copyright (c) 2015 Mohamed Aslan <maslan@sce.carleton.ca>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <endian.h>
21 #include <err.h>
23 #include "libof.h"
24 #include "of10.h"
26 static void of10_init(struct of_controller *);
27 static int of10_handshake(struct of_controller *, struct of_dataplane *);
28 static int of10_recv(struct of_controller *, struct of_dataplane *, struct ofp_header *);
29 static int of10_ping(struct of_controller *, struct of_dataplane *);
31 static struct of_protocol ofp10 = {
32 .version = OFP_VERSION_10,
33 .init = of10_init,
34 .handshake = of10_handshake,
35 .recv = of10_recv,
36 .ping = of10_ping
39 static void
40 of10_print_header(const struct ofp_header *hdr)
42 printf("header -> {version = %d, type = %d, length = %hu, xid = %x}\n",
43 (unsigned int)hdr->version,
44 (unsigned int)hdr->type,
45 be16toh(hdr->length),
46 (unsigned int)be32toh(hdr->xid));
49 static uint64_t
50 xid()
52 return (uint64_t)((uint64_t)arc4random() << 32 | arc4random());
55 static int
56 handle_echo_request(struct of_controller *ctl, struct of_dataplane *dp, const struct ofp_header *msg_in)
58 struct ofp_header msg_out;
60 /* send ECHO_REPLY */
61 msg_out.version = 0x1;
62 msg_out.type = OFPT10_ECHO_REPLY;
63 msg_out.length = htobe16(sizeof(struct ofp_header));
64 msg_out.xid = msg_in->xid;
65 printf("sending: ");
66 of10_print_header(&msg_out);
67 ctl->send(ctl, dp, &msg_out);
68 return 1;
71 static int
72 handle_features_reply(struct of_controller *ctl, struct of_dataplane *dp, const struct ofp_header *msg)
74 uintptr_t ptr;
75 uint64_t dpid = 0;
77 ptr = (uintptr_t)dp;
78 dp->sw_features = (struct ofp_header *)malloc(sizeof(struct of10_switch_features));
79 if (dp->sw_features == NULL)
80 return 0;
81 memcpy((void *)(dp->sw_features), msg, sizeof(struct of10_switch_features));
82 dpid = be64toh(((struct of10_switch_features *)(dp->sw_features))->datapath_id);
83 if (!hashtab_put(&(ctl->dpids), (void *)(&dpid), sizeof(uint64_t), (void *)(&ptr), sizeof(uintptr_t)))
84 errx(1, "hashtab_put");
85 #ifdef DEBUG
86 printf("datapath id: 0x%llx\n", dpid);
87 #endif
88 return 1;
91 static int
92 send_features_request(struct of_controller *ctl, struct of_dataplane *dp)
94 struct ofp_header msg;
96 msg.version = OFP_VERSION_10;
97 msg.type = OFPT10_FEATURES_REQUEST;
98 msg.length = htobe16(sizeof(struct ofp_header));
99 msg.xid = xid();
100 printf("sending: ");
101 of10_print_header(&msg);
102 ctl->send(ctl, dp, &msg);
103 return 1;
106 static void
107 of10_init(struct of_controller *ctl)
112 static int
113 of10_handshake(struct of_controller *ctl, struct of_dataplane *dp)
115 struct ofp_header msg;
117 /* send HELLO */
118 msg.version = 0x1;
119 msg.type = OFPT10_HELLO;
120 msg.length = htobe16(sizeof(struct ofp_header));
121 msg.xid = xid();
122 printf("sending: HELLO ");
123 of10_print_header(&msg);
124 ctl->send(ctl, dp, &msg);
125 return 1;
128 static int
129 of10_ping(struct of_controller *ctl, struct of_dataplane *dp)
131 struct ofp_header msg;
133 /* send ECHO_REQUEST */
134 msg.version = 0x1;
135 msg.type = OFPT10_ECHO_REQUEST;
136 msg.length = htobe16(sizeof(struct ofp_header));
137 msg.xid = xid();
138 printf("sending: EHCO_REQUEST ");
139 of10_print_header(&msg);
140 ctl->send(ctl, dp, &msg);
141 return 1;
144 static int
145 of10_recv(struct of_controller *ctl, struct of_dataplane *dp, struct ofp_header *msg)
147 struct of_event *ev;
149 if (msg == NULL)
150 return 0;
151 ev = (struct of_event *)malloc(sizeof(struct of_event));
152 ev->dp = dp;
154 #ifdef DEBUG
155 of10_print_header(msg);
156 #endif
157 switch (msg->type) {
158 case OFPT10_HELLO:
159 #ifdef DEBUG
160 printf("OFPT_HELLO.\n");
161 #endif
162 /* TODO: check for supported OpenFlow version */
163 dp->protocol = of10_protocol();
164 /* assume we already sent our hello message during handsaking via of10_init() */
165 if (!send_features_request(ctl, dp))
166 return 0;
167 break;
168 case OFPT10_OFPT_ERROR:
169 #ifdef DEBUG
170 printf("OFPT_ERROR.\n");
171 #endif
172 break;
173 case OFPT10_ECHO_REQUEST:
174 #ifdef DEBUG
175 printf("OFPT_ECHO_REQUEST.\n");
176 #endif
177 if (!handle_echo_request(ctl, dp, msg))
178 return 0;
179 break;
180 case OFPT10_ECHO_REPLY:
181 #ifdef DEBUG
182 printf("OFPT_ECHO_REPLY.\n");
183 #endif
184 break;
185 case OFPT10_FEATURES_REQUEST:
186 #ifdef DEBUG
187 printf("XXX OFPT_FEATURES_REQUEST.\n");
188 #endif
189 break;
190 case OFPT10_FEATURES_REPLY:
191 #ifdef DEBUG
192 printf("OFPT_FEATURES_REPLY.\n");
193 #endif
194 if (!handle_features_reply(ctl, dp, msg))
195 break;
196 dp->ready = 1;
197 /* generate a connection up event */
198 ev->type = OFEV_CONNECTION_UP;
199 if (ctl->of_handler != NULL)
200 ctl->of_handler(ctl, ev);
201 break;
202 case OFPT10_PACKET_IN:
203 #ifdef DEBUG
204 printf("OFPT_PACKET_IN.\n");
205 #endif
206 /* generate a protocol message event */
207 ev->type = OFEV_PROTO_MESSAGE;
208 ev->ofp_hdr = msg;
209 if (dp->ready && ctl->of_handler != NULL)
210 ctl->of_handler(ctl, ev);
211 break;
212 case OFPT10_STATS_REPLY:
213 #ifdef DEBUG
214 printf("OFPT_STATS_REPLY.\n");
215 #endif
216 /* generate a protocol message event */
217 ev->type = OFEV_PROTO_MESSAGE;
218 ev->ofp_hdr = msg;
219 if (dp->ready && ctl->of_handler != NULL)
220 ctl->of_handler(ctl, ev);
221 default:
222 #ifdef DEBUG
223 printf("XXX UNSUPPORTED MESSAGE TYPE.\n");
224 #endif
225 break;
227 free(ev);
228 return 1;
231 const struct of_protocol *
232 of10_protocol()
234 return &ofp10;