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.
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
,
34 .handshake
= of10_handshake
,
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
,
46 (unsigned int)be32toh(hdr
->xid
));
52 return (uint64_t)((uint64_t)arc4random() << 32 | arc4random());
56 handle_echo_request(struct of_controller
*ctl
, struct of_dataplane
*dp
, const struct ofp_header
*msg_in
)
58 struct ofp_header msg_out
;
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
;
66 of10_print_header(&msg_out
);
67 ctl
->send(ctl
, dp
, &msg_out
);
72 handle_features_reply(struct of_controller
*ctl
, struct of_dataplane
*dp
, const struct ofp_header
*msg
)
78 dp
->sw_features
= (struct ofp_header
*)malloc(sizeof(struct of10_switch_features
));
79 if (dp
->sw_features
== NULL
)
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");
86 printf("datapath id: 0x%llx\n", dpid
);
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
));
101 of10_print_header(&msg
);
102 ctl
->send(ctl
, dp
, &msg
);
107 of10_init(struct of_controller
*ctl
)
113 of10_handshake(struct of_controller
*ctl
, struct of_dataplane
*dp
)
115 struct ofp_header msg
;
119 msg
.type
= OFPT10_HELLO
;
120 msg
.length
= htobe16(sizeof(struct ofp_header
));
122 printf("sending: HELLO ");
123 of10_print_header(&msg
);
124 ctl
->send(ctl
, dp
, &msg
);
129 of10_ping(struct of_controller
*ctl
, struct of_dataplane
*dp
)
131 struct ofp_header msg
;
133 /* send ECHO_REQUEST */
135 msg
.type
= OFPT10_ECHO_REQUEST
;
136 msg
.length
= htobe16(sizeof(struct ofp_header
));
138 printf("sending: EHCO_REQUEST ");
139 of10_print_header(&msg
);
140 ctl
->send(ctl
, dp
, &msg
);
145 of10_recv(struct of_controller
*ctl
, struct of_dataplane
*dp
, struct ofp_header
*msg
)
151 ev
= (struct of_event
*)malloc(sizeof(struct of_event
));
155 of10_print_header(msg
);
160 printf("OFPT_HELLO.\n");
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
))
168 case OFPT10_OFPT_ERROR
:
170 printf("OFPT_ERROR.\n");
173 case OFPT10_ECHO_REQUEST
:
175 printf("OFPT_ECHO_REQUEST.\n");
177 if (!handle_echo_request(ctl
, dp
, msg
))
180 case OFPT10_ECHO_REPLY
:
182 printf("OFPT_ECHO_REPLY.\n");
185 case OFPT10_FEATURES_REQUEST
:
187 printf("XXX OFPT_FEATURES_REQUEST.\n");
190 case OFPT10_FEATURES_REPLY
:
192 printf("OFPT_FEATURES_REPLY.\n");
194 if (!handle_features_reply(ctl
, dp
, msg
))
197 /* generate a connection up event */
198 ev
->type
= OFEV_CONNECTION_UP
;
199 if (ctl
->of_handler
!= NULL
)
200 ctl
->of_handler(ctl
, ev
);
202 case OFPT10_PACKET_IN
:
204 printf("OFPT_PACKET_IN.\n");
206 /* generate a protocol message event */
207 ev
->type
= OFEV_PROTO_MESSAGE
;
209 if (dp
->ready
&& ctl
->of_handler
!= NULL
)
210 ctl
->of_handler(ctl
, ev
);
212 case OFPT10_STATS_REPLY
:
214 printf("OFPT_STATS_REPLY.\n");
216 /* generate a protocol message event */
217 ev
->type
= OFEV_PROTO_MESSAGE
;
219 if (dp
->ready
&& ctl
->of_handler
!= NULL
)
220 ctl
->of_handler(ctl
, ev
);
223 printf("XXX UNSUPPORTED MESSAGE TYPE.\n");
231 const struct of_protocol
*