blob: 25594d4cc74f8b1b0cdc162192ede26c07f7a5f5 [file] [log] [blame]
Shad Ansari01b0e652018-04-05 21:02:53 +00001/*
2 Copyright (C) 2018 Open Networking Foundation
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include <iostream>
19#include <memory>
20#include <string>
21
22#include "Queue.h"
23#include <iostream>
24#include <sstream>
25
26#include "server.h"
27#include "indications.h"
28
29extern "C"
30{
31#include <bcmos_system.h>
32#include <bal_api.h>
33#include <bal_api_end.h>
34}
35#include <openolt.grpc.pb.h>
36
37using grpc::Server;
38using grpc::ServerBuilder;
39using grpc::ServerContext;
40using grpc::ServerWriter;
41
42const char *serverPort = "0.0.0.0:9191";
43
44class OpenoltService final : public openolt::Openolt::Service {
45
46 Status ActivateOnu(
47 ServerContext* context,
48 const openolt::Onu* request,
49 openolt::Empty* response) override {
50 return ActivateOnu_(
51 request->intf_id(),
52 request->onu_id(),
53 ((request->serial_number()).vendor_id()).c_str(),
54 ((request->serial_number()).vendor_specific()).c_str());
55 }
56
57 Status OmciMsgOut(
58 ServerContext* context,
59 const openolt::OmciMsg* request,
60 openolt::Empty* response) override {
61 return OmciMsgOut_(
62 request->intf_id(),
63 request->onu_id(),
64 request->pkt());
65 }
66
67 Status FlowAdd(
68 ServerContext* context,
69 const openolt::Flow* request,
70 openolt::Empty* response) override {
71 return FlowAdd_(
72 request->onu_id(),
73 request->flow_id(),
74 request->flow_type(),
75 request->access_intf_id(),
76 request->network_intf_id(),
77 request->gemport_id(),
78 request->classifier(),
79 request->action());
80 }
81
82 Status EnableIndication(
83 ServerContext* context,
84 const ::openolt::Empty* request,
85 ServerWriter<openolt::Indication>* writer) override {
86 while (1) {
87 auto oltInd = oltIndQ.pop();
88 writer->Write(oltInd);
89 //oltInd.release_olt_ind()
90 }
91 return Status::OK;
92 }
93};
94
95void RunServer() {
96 OpenoltService service;
97 std::string server_address(serverPort);
98 ServerBuilder builder;
99
100 builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
101 builder.RegisterService(&service);
102
103 std::unique_ptr<Server> server(builder.BuildAndStart());
104
105 std::cout << "Server listening on " << server_address << std::endl;
106
107 server->Wait();
108}
109
110Status Enable_() {
111 static bool enabled = false;
112 bcmbal_access_terminal_cfg acc_term_obj;
113 bcmbal_access_terminal_key key = { };
114
115 if (!enabled) {
116 std::cout << "Enable OLT" << std::endl;
117 key.access_term_id = DEFAULT_ATERM_ID;
118 BCMBAL_CFG_INIT(&acc_term_obj, access_terminal, key);
119 BCMBAL_CFG_PROP_SET(&acc_term_obj, access_terminal, admin_state, BCMBAL_STATE_UP);
120 if (bcmbal_cfg_set(DEFAULT_ATERM_ID, &(acc_term_obj.hdr))) {
121 std::cout << "ERROR: Failed to enable OLT" << std::endl;
122 return Status(grpc::StatusCode::INTERNAL, "Failed to enable OLT");
123 }
124 enabled = true;
125 }
126 return Status::OK;
127}
128
129Status EnablePonIf_(uint32_t intf_id) {
130 bcmbal_interface_cfg interface_obj;
131 bcmbal_interface_key interface_key;
132
133 interface_key.intf_id = intf_id;
134 interface_key.intf_type = BCMBAL_INTF_TYPE_PON;
135
136 BCMBAL_CFG_INIT(&interface_obj, interface, interface_key);
137 BCMBAL_CFG_PROP_SET(&interface_obj, interface, admin_state, BCMBAL_STATE_UP);
138
139 if (bcmbal_cfg_set(DEFAULT_ATERM_ID, &(interface_obj.hdr))) {
140 std::cout << "ERROR: Failed to enable PON interface: " << intf_id << std::endl;
141 return Status(grpc::StatusCode::INTERNAL, "Failed to enable PON interface");
142 }
143
144 return Status::OK;
145}
146
147Status ActivateOnu_(uint32_t intf_id, uint32_t onu_id,
148 const char *vendor_id, const char *vendor_specific) {
149
150 bcmbal_subscriber_terminal_cfg sub_term_obj = {};
151 bcmbal_subscriber_terminal_key subs_terminal_key;
152 bcmbal_serial_number serial_num = {};
153 bcmbal_registration_id registration_id = {};
154
155 std::cout << "Enabling ONU " << onu_id << " on PON " << intf_id << std::endl;
156 std::cout << "Vendor Id " << vendor_id
157 << "Vendor Specific Id " << vendor_specific
158 << std::endl;
159
160 subs_terminal_key.sub_term_id = onu_id;
161 subs_terminal_key.intf_id = intf_id;
162 BCMBAL_CFG_INIT(&sub_term_obj, subscriber_terminal, subs_terminal_key);
163
164 memcpy(serial_num.vendor_id, vendor_id, 4);
165 memcpy(serial_num.vendor_specific, vendor_specific, 4);
166 BCMBAL_CFG_PROP_SET(&sub_term_obj, subscriber_terminal, serial_number, serial_num);
167
168 // FIXME - Use a default (all zeros) registration id.
169 memset(registration_id.arr, 0, sizeof(registration_id.arr));
170 BCMBAL_CFG_PROP_SET(&sub_term_obj, subscriber_terminal, registration_id, registration_id);
171
172 BCMBAL_CFG_PROP_SET(&sub_term_obj, subscriber_terminal, admin_state, BCMBAL_STATE_UP);
173
174 if (bcmbal_cfg_set(DEFAULT_ATERM_ID, &(sub_term_obj.hdr))) {
175 std::cout << "ERROR: Failed to enable ONU: " << std::endl;
176 return Status(grpc::StatusCode::INTERNAL, "Failed to enable ONU");
177 }
178
179 return SchedAdd_(intf_id, onu_id, mk_agg_port_id(onu_id));
180
181 //return Status::OK;
182}
183
184#define MAX_CHAR_LENGTH 20
185#define MAX_OMCI_MSG_LENGTH 44
186Status OmciMsgOut_(uint32_t intf_id, uint32_t onu_id, const std::string pkt) {
187 bcmbal_u8_list_u32_max_2048 buf; /* A structure with a msg pointer and length value */
188 bcmos_errno err = BCM_ERR_OK;
189
190 /* The destination of the OMCI packet is a registered ONU on the OLT PON interface */
191 bcmbal_dest proxy_pkt_dest;
192
193 proxy_pkt_dest.type = BCMBAL_DEST_TYPE_ITU_OMCI_CHANNEL;
194 proxy_pkt_dest.u.itu_omci_channel.sub_term_id = onu_id;
195 proxy_pkt_dest.u.itu_omci_channel.intf_id = intf_id;
196
197 // ???
198 if ((pkt.size()/2) > MAX_OMCI_MSG_LENGTH) {
199 buf.len = MAX_OMCI_MSG_LENGTH;
200 } else {
201 buf.len = pkt.size()/2;
202 }
203
204 /* Send the OMCI packet using the BAL remote proxy API */
205 uint16_t idx1 = 0;
206 uint16_t idx2 = 0;
207 uint8_t arraySend[buf.len];
208 char str1[MAX_CHAR_LENGTH];
209 char str2[MAX_CHAR_LENGTH];
210 memset(&arraySend, 0, buf.len);
211
212 std::cout << "Sending omci msg to ONU of length is "
213 << buf.len
214 << std::endl;
215
216 for (idx1=0,idx2=0; idx1<((buf.len)*2); idx1++,idx2++) {
217 sprintf(str1,"%c", pkt[idx1]);
218 sprintf(str2,"%c", pkt[++idx1]);
219 strcat(str1,str2);
220 arraySend[idx2] = strtol(str1, NULL, 16);
221 }
222
223 buf.val = (uint8_t *)malloc((buf.len)*sizeof(uint8_t));
224 memcpy(buf.val,(uint8_t *)arraySend,buf.len);
225
226 std::cout << "After converting bytes to hex "
227 << buf.val << buf.len << std::endl;
228
229 err = bcmbal_pkt_send(0, proxy_pkt_dest,
230 (const char *)(buf.val), buf.len);
231
232 std::cout << "OMCI request msg of length " << buf.len
233 << " sent to ONU" << onu_id
234 << " through PON " << intf_id << std::endl;
235
236 free(buf.val);
237
238 return Status::OK;
239}
240
241Status FlowAdd_(uint32_t onu_id,
242 uint32_t flow_id, const std::string flow_type,
243 uint32_t access_intf_id, uint32_t network_intf_id,
244 uint32_t gemport_id,
245 const ::openolt::Classifier& classifier,
246 const ::openolt::Action& action) {
247 bcmos_errno err;
248 bcmbal_flow_cfg cfg;
249 bcmbal_flow_key key = { };
250
251 std::cout << "flow add -"
252 << " intf_id:" << access_intf_id
253 << " onu_id:" << onu_id
254 << " flow_id:" << flow_id
255 << " flow_type:" << flow_type
256 << " gemport_id:" << gemport_id
257 << " network_intf_id:" << network_intf_id
258 << std::endl;
259
260 key.flow_id = flow_id;
261 if (flow_type.compare("upstream") == 0 ) {
262 key.flow_type = BCMBAL_FLOW_TYPE_UPSTREAM;
263 } else if (flow_type.compare("downstream") == 0) {
264 key.flow_type = BCMBAL_FLOW_TYPE_DOWNSTREAM;
265 } else {
266 std::cout << "Invalid flow type " << flow_type << std::endl;
267 return Status::CANCELLED;
268 }
269
270 BCMBAL_CFG_INIT(&cfg, flow, key);
271
272 BCMBAL_CFG_PROP_SET(&cfg, flow, admin_state, BCMBAL_STATE_UP);
273 BCMBAL_CFG_PROP_SET(&cfg, flow, access_int_id, access_intf_id);
274 BCMBAL_CFG_PROP_SET(&cfg, flow, network_int_id, network_intf_id);
275 BCMBAL_CFG_PROP_SET(&cfg, flow, sub_term_id, onu_id);
276 BCMBAL_CFG_PROP_SET(&cfg, flow, svc_port_id, gemport_id);
277
278 {
279 bcmbal_classifier val = { };
280
281 if (classifier.o_tpid()) {
282 val.o_tpid = classifier.o_tpid();
283 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_O_TPID;
284 }
285
286 if (classifier.o_vid()) {
287 val.o_vid = classifier.o_vid();
288 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_O_VID;
289 }
290
291 if (classifier.i_tpid()) {
292 val.i_tpid = classifier.i_tpid();
293 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_I_TPID;
294 }
295
296 if (classifier.i_vid()) {
297 val.i_vid = classifier.i_vid();
298 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_I_VID;
299 }
300
301 if (classifier.o_pbits()) {
302 val.o_pbits = classifier.o_pbits();
303 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_O_PBITS;
304 }
305
306 if (classifier.i_pbits()) {
307 val.i_pbits = classifier.i_pbits();
308 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_I_PBITS;
309 }
310
311 if (classifier.eth_type()) {
312 val.ether_type = classifier.eth_type();
313 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_ETHER_TYPE;
314 }
315
316 /*
317 if (classifier.dst_mac()) {
318 val.dst_mac = classifier.dst_mac();
319 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_DST_MAC;
320 }
321
322 if (classifier.src_mac()) {
323 val.src_mac = classifier.src_mac();
324 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_SRC_MAC;
325 }
326 */
327
328 if (classifier.ip_proto()) {
329 val.ip_proto = classifier.ip_proto();
330 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_IP_PROTO;
331 }
332
333 /*
334 if (classifier.dst_ip()) {
335 val.dst_ip = classifier.dst_ip();
336 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_DST_IP;
337 }
338
339 if (classifier.src_ip()) {
340 val.src_ip = classifier.src_ip();
341 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_SRC_IP;
342 }
343 */
344
345 if (classifier.src_port()) {
346 val.src_port = classifier.src_port();
347 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_SRC_PORT;
348 }
349
350 if (classifier.dst_port()) {
351 val.dst_port = classifier.dst_port();
352 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_DST_PORT;
353 }
354
355 if (!classifier.pkt_tag_type().empty()) {
356 if (classifier.pkt_tag_type().compare("untagged") == 0) {
357 val.pkt_tag_type = BCMBAL_PKT_TAG_TYPE_UNTAGGED;
358 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_PKT_TAG_TYPE;
359 } else if (classifier.pkt_tag_type().compare("single_tag") == 0) {
360 val.pkt_tag_type = BCMBAL_PKT_TAG_TYPE_SINGLE_TAG;
361 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_PKT_TAG_TYPE;
362 } else if (classifier.pkt_tag_type().compare("double_tag") == 0) {
363 val.pkt_tag_type = BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG;
364 val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_PKT_TAG_TYPE;
365 }
366 }
367
368 BCMBAL_CFG_PROP_SET(&cfg, flow, classifier, val);
369 }
370
371 {
372 bcmbal_action val = { };
373
374 const ::openolt::ActionCmd& cmd = action.cmd();
375
376 if (cmd.add_outer_tag()) {
377 val.cmds_bitmask |= BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG;
378 val.presence_mask |= BCMBAL_ACTION_ID_CMDS_BITMASK;
379 }
380
381 if (cmd.remove_outer_tag()) {
382 val.cmds_bitmask |= BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG;
383 val.presence_mask |= BCMBAL_ACTION_ID_CMDS_BITMASK;
384 }
385
386 if (cmd.trap_to_host()) {
387 val.cmds_bitmask |= BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST;
388 val.presence_mask |= BCMBAL_ACTION_ID_CMDS_BITMASK;
389 }
390
391 if (action.o_vid()) {
392 val.o_vid = action.o_vid();
393 val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_O_VID;
394 }
395
396 if (action.o_pbits()) {
397 val.o_pbits = action.o_pbits();
398 val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_O_PBITS;
399 }
400
401 if (action.o_tpid()) {
402 val.o_tpid = action.o_tpid();
403 val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_O_TPID;
404 }
405
406 if (action.i_vid()) {
407 val.i_vid = action.i_vid();
408 val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_I_VID;
409 }
410
411 if (action.i_pbits()) {
412 val.i_pbits = action.i_pbits();
413 val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_I_PBITS;
414 }
415
416 if (action.i_tpid()) {
417 val.i_tpid = action.i_tpid();
418 val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_I_TPID;
419 }
420
421 BCMBAL_CFG_PROP_SET(&cfg, flow, action, val);
422 }
423
424 {
425 bcmbal_tm_sched_id val;
426 val = (bcmbal_tm_sched_id) mk_sched_id(onu_id);
427 BCMBAL_CFG_PROP_SET(&cfg, flow, dba_tm_sched_id, val);
428 }
429
430 if (bcmbal_cfg_set(DEFAULT_ATERM_ID, &(cfg.hdr))) {
431 std::cout << "ERROR: flow add failed" << std::endl;
432 return Status(grpc::StatusCode::INTERNAL, "flow add failed");
433 }
434
435 return Status::OK;
436}
437
438Status SchedAdd_(int intf_id, int onu_id, int agg_port_id) {
439 bcmbal_tm_sched_cfg cfg;
440 bcmbal_tm_sched_key key = { };
441 bcmbal_tm_sched_type sched_type;
442
443 key.id = mk_sched_id(onu_id);
444 key.dir = BCMBAL_TM_SCHED_DIR_US;
445
446 BCMBAL_CFG_INIT(&cfg, tm_sched, key);
447
448 {
449 bcmbal_tm_sched_owner val = { };
450
451 val.type = BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT;
452 val.u.agg_port.intf_id = (bcmbal_intf_id) intf_id;
453 val.u.agg_port.presence_mask = val.u.agg_port.presence_mask | BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_INTF_ID;
454 val.u.agg_port.sub_term_id = (bcmbal_sub_id) onu_id;
455 val.u.agg_port.presence_mask = val.u.agg_port.presence_mask | BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_SUB_TERM_ID;
456
457 val.u.agg_port.agg_port_id = (bcmbal_aggregation_port_id) agg_port_id;
458 val.u.agg_port.presence_mask = val.u.agg_port.presence_mask | BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_AGG_PORT_ID;
459
460 BCMBAL_CFG_PROP_SET(&cfg, tm_sched, owner, val);
461 }
462
463 if (bcmbal_cfg_set(DEFAULT_ATERM_ID, &(cfg.hdr))) {
464 std::cout << "ERROR: Failed to create upstream DBA sched"
465 << " id:" << key.id
466 << " intf_id:" << intf_id
467 << " onu_id:" << onu_id << std::endl;
468 return Status(grpc::StatusCode::INTERNAL, "Failed to create upstream DBA sched");
469 //return 1;
470 }
471 std::cout << "create upstream DBA sched"
472 << " id:" << key.id
473 << " intf_id:" << intf_id
474 << " onu_id:" << onu_id << std::endl;
475
476 return Status::OK;
477 //return 0;
478}