blob: 60cb073311af3087dcc58279ec72c0138a786e0f [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2 <:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7 Unless you and Broadcom execute a separate written software license
8 agreement governing use of this software, this software is licensed
9 to you under the terms of the GNU General Public License version 2
10 (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11 with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22 Not withstanding the above, under no circumstances may you combine
23 this software in any way with any other Broadcom software provided
24 under a license other than the GPL, without Broadcom's express prior
25 written consent.
26
27 :>
28 */
29
30#include <bcmos_system.h>
31#include <bcmolt_api.h>
32#include <bcmolt_model_types.h>
33#include <bcmcli_session.h>
34#include <bcmolt_msg_pack.h>
35#include <bcm_dev_log.h>
36#include <encrypt_oam.h>
37#include <oam_defs.h>
38#include "bcmolt_epon_hde.h"
39
40#define HDE_TASK_MSG_Q_SIZE 64
41#define ENC_KEY_LENGTH_KEY 16
42#define HDE_MAX_NUM_LINKS 512
43#define KEY_EXCHANGE_PERIOD 15
44
45typedef enum
46{
47 HDE_EVENT_ENABLE_ENCRYPTION,
48 HDE_EVENT_DISABLE_ENCRYPTION,
49 HDE_EVENT_FRAME_RX,
50 HDE_EVENT_OAM_TIMEOUT,
51 HDE_EVENT__NUM_OF
52} hde_event;
53
54typedef enum
55{
56 HDE_STATE_NOT_ENCRYPTED,
57 HDE_STATE_ENCRYPTED,
58 HDE_STATE_WAITING_FOR_OAM_ACK,
59 HDE_STATE__NUM_OF
60} hde_state;
61
62typedef struct
63{
64 bcmos_msg os_msg;
65 bcmolt_msg *rx;
66 hde_key key;
67 hde_event event;
68} hde_task_msg;
69
70typedef struct
71{
72 hde_key hde_link;
73 hde_state state;
74 bcmos_timer oam_timeout_timer;
75 bcmolt_epon_link_rate link_rate;
76 bcmolt_epon_llid llid;
77 bcmos_mac_address corresponding_pon_port_mac;
78} hde_link_data;
79
80static struct
81{
82 bcmos_task task;
83 dev_log_id log_id[BCMTR_MAX_OLTS];
84 hde_link_data *links;
85 uint16_t num_links;
86} hde_data;
87
88static bcmos_bool is_running = BCMOS_FALSE;
89
90typedef void (*link_state_handler)(hde_link_data *hde_link, const bcmolt_msg *ind);
91
92static const char *get_state_string(hde_state state)
93{
94 switch (state)
95 {
96 case HDE_STATE_NOT_ENCRYPTED:
97 return "not encrypted";
98 case HDE_STATE_ENCRYPTED:
99 return "encrypted";
100 case HDE_STATE_WAITING_FOR_OAM_ACK:
101 return "waiting for oam ack";
102 default:
103 return "UNKNOWN STATE!!!";
104 }
105}
106
107static bcmos_errno set_new_key(const hde_key *hde_link, bcmolt_encryption_information_container *new_key, bcmolt_epon_key_choice key_choice, bcmolt_epon_encryption_mode mode)
108{
109 bcmolt_epon_link_cfg link_cfg;
110 bcmolt_epon_encryption_config encryption_config = { };
111
112 // Up/down format must match even when doing DS only
113 encryption_config.upstream_encryption_information.format = new_key->format;
114
115 encryption_config.downstream_encryption_information = *new_key;
116 encryption_config.downstream_key_choice = key_choice;
117 encryption_config.downstream_mode = mode;
118 bcmolt_epon_link_key link_key =
119 {
120 .epon_ni = hde_link->epon_ni,
121 .mac_address = hde_link->mac_addr
122 };
123 BCMOLT_CFG_INIT(&link_cfg, epon_link, link_key);
124 BCMOLT_CFG_PROP_SET(&link_cfg, epon_link, epon_encryption, encryption_config);
125 return bcmolt_cfg_set(hde_link->device_id, &link_cfg.hdr);
126}
127
128static bcmos_errno set_pon_encryption_if_needed(const hde_key *hde_link)
129{
130 // First check the current state of the PON's encryption mode.
131 bcmos_errno rc;
132 bcmolt_epon_ni_cfg pon_cfg;
133 bcmolt_epon_ni_key pon_key = { .epon_ni = hde_link->epon_ni };
134 BCMOLT_CFG_INIT(&pon_cfg, epon_ni, pon_key);
135 BCMOLT_CFG_PROP_GET(&pon_cfg, epon_ni, encryption_cfg);
136 rc = bcmolt_cfg_get(hde_link->device_id, &pon_cfg.hdr);
137 if (rc != BCM_ERR_OK)
138 {
139 BCM_LOG(ERROR, hde_data.log_id[hde_link->device_id], "Failure - Cannot query PON encryption mode!.\n");
140 return rc;
141 }
142
143 if (pon_cfg.data.encryption_cfg.downstream_encryption_mode != BCMOLT_EPON_ENCRYPTION_MODE_EPON_ZERO_OVERHEAD_AES)
144 {
145 // Encryption mode is not correctly set on the PON, so set it now.
146 pon_cfg.data.encryption_cfg.downstream_encryption_mode = BCMOLT_EPON_ENCRYPTION_MODE_EPON_ZERO_OVERHEAD_AES;
147 pon_cfg.data.encryption_cfg.upstream_encryption_mode = BCMOLT_EPON_ENCRYPTION_MODE_NO_ENCRYPTION;
148 rc = bcmolt_cfg_set(hde_link->device_id, &pon_cfg.hdr);
149 if (rc != BCM_ERR_OK)
150 {
151 BCM_LOG(ERROR, hde_data.log_id[hde_link->device_id], "Failure - Cannot set PON encryption mode!.\n");
152 return rc;
153 }
154 }
155
156 return BCM_ERR_OK;
157}
158
159static bcmolt_epon_link_rate get_link_rate(const hde_key *hde_link)
160{
161 bcmos_errno rc;
162 bcmolt_epon_link_cfg link_cfg;
163 bcmolt_epon_link_key link_key =
164 {
165 .epon_ni = hde_link->epon_ni,
166 .mac_address = hde_link->mac_addr
167 };
168 BCMOLT_CFG_INIT(&link_cfg, epon_link, link_key);
169 BCMOLT_CFG_PROP_GET(&link_cfg, epon_link, link_rate);
170 rc = bcmolt_cfg_get(hde_link->device_id, &link_cfg.hdr);
171 if (rc != BCM_ERR_OK)
172 {
173 BCM_LOG(
174 ERROR,
175 hde_data.log_id[hde_link->device_id],
176 "Failure - cannot query link rate for link %02x:%02x:%02x:%02x:%02x:%02x!.\n",
177 hde_link->mac_addr.u8[0],
178 hde_link->mac_addr.u8[1],
179 hde_link->mac_addr.u8[2],
180 hde_link->mac_addr.u8[3],
181 hde_link->mac_addr.u8[4],
182 hde_link->mac_addr.u8[5]);
183 }
184 return link_cfg.data.link_rate;
185}
186
187static bcmos_mac_address get_pon_mac(const hde_key *hde_link)
188{
189 bcmos_errno rc;
190 bcmolt_epon_ni_cfg pon_cfg;
191 bcmolt_epon_ni_key pon_key = { .epon_ni = hde_link->epon_ni };
192 BCMOLT_CFG_INIT(&pon_cfg, epon_ni, pon_key);
193 BCMOLT_CFG_PROP_GET(&pon_cfg, epon_ni, mac_address);
194 rc = bcmolt_cfg_get(hde_link->device_id, &pon_cfg.hdr);
195 if (rc != BCM_ERR_OK)
196 {
197 BCM_LOG(ERROR, hde_data.log_id[hde_link->device_id], "Failure - Cannot query PON mac address!.\n");
198 }
199 return pon_cfg.data.mac_address;
200}
201
202static bcmolt_epon_llid get_llid(const hde_key *hde_link)
203{
204 bcmos_errno rc;
205 bcmolt_epon_link_cfg link_cfg;
206 bcmolt_epon_link_key link_key =
207 {
208 .epon_ni = hde_link->epon_ni,
209 .mac_address = hde_link->mac_addr
210 };
211 BCMOLT_CFG_INIT(&link_cfg, epon_link, link_key);
212 BCMOLT_CFG_PROP_GET(&link_cfg, epon_link, llid);
213 rc = bcmolt_cfg_get(hde_link->device_id, &link_cfg.hdr);
214 if (rc != BCM_ERR_OK)
215 {
216 BCM_LOG(
217 ERROR,
218 hde_data.log_id[hde_link->device_id],
219 "Failure - cannot query LLID for link %02x:%02x:%02x:%02x:%02x:%02x!.\n",
220 hde_link->mac_addr.u8[0],
221 hde_link->mac_addr.u8[1],
222 hde_link->mac_addr.u8[2],
223 hde_link->mac_addr.u8[3],
224 hde_link->mac_addr.u8[4],
225 hde_link->mac_addr.u8[5]);
226 }
227 return link_cfg.data.llid;
228}
229
230/* By spec the SCI is the LLID of the link appended to the corresponding epon port mac address */
231static void create_sci(const bcmos_mac_address *epon_port_mac, bcmolt_epon_llid llid, uint8_t *sci)
232{
233 sci[7] = (uint8_t) llid;
234 sci[6] = (uint8_t) (llid >> 8);
235 sci[5] = epon_port_mac->u8[5];
236 sci[4] = epon_port_mac->u8[4];
237 sci[3] = epon_port_mac->u8[3];
238 sci[2] = epon_port_mac->u8[2];
239 sci[1] = epon_port_mac->u8[1];
240 sci[0] = epon_port_mac->u8[0];
241}
242
243static void handle_not_encrypted_enable_encryption(hde_link_data *hde_link, const bcmolt_msg *ind)
244{
245 dpoe_encrypt_mode mode = DPOE_ENCRYPT_MODE_NONE;
246 // Retreive useful link info and store it to save messages later.
247 hde_link->link_rate = get_link_rate(&hde_link->hde_link);
248 hde_link->corresponding_pon_port_mac = get_pon_mac(&hde_link->hde_link);
249 hde_link->llid = get_llid(&hde_link->hde_link);
250
251 if (hde_link->link_rate == BCMOLT_EPON_LINK_RATE_TEN_TEN || hde_link->link_rate == BCMOLT_EPON_LINK_RATE_TEN_ONE)
252 {
253 mode = DPOE_ENCRYPT_MODE_10DOWN;
254 }
255 else if (hde_link->link_rate == BCMOLT_EPON_LINK_RATE_ONE_ONE)
256 {
257 mode = DPOE_ENCRYPT_MODE_1DOWN;
258 }
259 else
260 {
261 BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id], "Failure - UNKNOWN LINK RATE!!!.\n");
262 }
263
264 dpoe_encrypt_oam_set_request_send(
265 &hde_link->hde_link,
266 KEY_EXCHANGE_PERIOD,
267 mode,
268 hde_link->corresponding_pon_port_mac);
269
270 bcmos_timer_start(&hde_link->oam_timeout_timer, HDE_ENABLE_OAM_WAIT_US + OAM_TIMEOUT_GRACE_PERIOD_US);
271
272 hde_link->state = HDE_STATE_WAITING_FOR_OAM_ACK;
273}
274
275static void handle_encrypted_disable_encryption(hde_link_data *hde_link, const bcmolt_msg *ind)
276{
277 bcmolt_encryption_information_container empty_key = { };
278 bcmos_errno rc;
279
280 // Turn off encryption on the embedded side.
281 rc = set_new_key(&hde_link->hde_link, &empty_key, BCMOLT_EPON_KEY_CHOICE_KEY_0, BCMOLT_EPON_ENCRYPTION_MODE_NO_ENCRYPTION);
282 if (rc != BCM_ERR_OK)
283 {
284 BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id],
285 "Failure - Cannot communicate with the embedded!.\n");
286 }
287
288 // Send the disable OAM to the link. Don't bother waiting for a response.
289 dpoe_encrypt_oam_set_request_send(&hde_link->hde_link, 0, DPOE_ENCRYPT_MODE_NONE, get_pon_mac(&hde_link->hde_link));
290
291 hde_link->state = HDE_STATE_NOT_ENCRYPTED;
292}
293
294static void handle_encrypted_frame_rx(hde_link_data *hde_link, const bcmolt_msg *ind)
295{
296 const bcmolt_epon_link_frame_captured *frame_captured = (const bcmolt_epon_link_frame_captured*) ind;
297 uint8_t new_key[16];
298 bcmolt_epon_key_choice key_choice;
299 bcmos_errno rc;
300 bcmolt_encryption_information_container key_for_embedded;
301 rc = dpoe_encrypt_oam_parse_new_key(&frame_captured->data.frame, new_key, &key_choice);
302 if (rc != BCM_ERR_OK)
303 {
304 // Not a DPoE new key, ignore it
305 return;
306 }
307
308 if (hde_link->link_rate == BCMOLT_EPON_LINK_RATE_TEN_TEN || hde_link->link_rate == BCMOLT_EPON_LINK_RATE_TEN_ONE)
309 {
310 uint8_t sci[8];
311 create_sci(&hde_link->corresponding_pon_port_mac, hde_link->llid, sci);
312 key_for_embedded.format = BCMOLT_EPON_ENCRYPTION_INFORMATION_FORMAT_CTR;
313 memcpy(key_for_embedded.u.ctr.key, new_key, sizeof(new_key));
314 memcpy(key_for_embedded.u.ctr.sci, sci, sizeof(sci));
315 }
316 else if (hde_link->link_rate == BCMOLT_EPON_LINK_RATE_ONE_ONE)
317 {
318 key_for_embedded.format = BCMOLT_EPON_ENCRYPTION_INFORMATION_FORMAT_CFB;
319 memcpy(key_for_embedded.u.cfb.key, new_key, sizeof(new_key));
320 }
321 else
322 {
323 BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id], "Failure - UNKNOWN LINK RATE!!!.\n");
324 }
325
326 rc = set_new_key(&hde_link->hde_link, &key_for_embedded, key_choice, BCMOLT_EPON_ENCRYPTION_MODE_EPON_ZERO_OVERHEAD_AES);
327 if (rc != BCM_ERR_OK)
328 {
329 BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id],
330 "Failure - Cannot communicate with the embedded!.\n");
331 }
332}
333
334static void handle_waiting_for_oam_ack_oam_timeout(hde_link_data *hde_link, const bcmolt_msg *ind)
335{
336 BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id], "Failure - No response to initial OAM.\n");
337 hde_link->state = HDE_STATE_NOT_ENCRYPTED;
338}
339
340static void handle_waiting_for_oam_ack_frame_rx(hde_link_data *hde_link, const bcmolt_msg *ind)
341{
342 const bcmolt_epon_link_frame_captured *frame_captured = (const bcmolt_epon_link_frame_captured*) ind;
343 uint8_t encrypt_mode_response;
344 uint8_t key_expiry_response;
345 bcmos_errno rc;
346
347 rc = dpoe_encrypt_oam_parse_set_response(&frame_captured->data.frame, &encrypt_mode_response, &key_expiry_response);
348 if (rc != BCM_ERR_OK)
349 {
350 // Not a encryption set reponse, ignore it
351 return;
352 }
353
354 /* 0 represents 'no error'. */
355 if ((encrypt_mode_response != 0) || (key_expiry_response != 0))
356 {
357 BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id],
358 "Failure - The link refused one of the requested TLVs.\n");
359 hde_link->state = HDE_STATE_NOT_ENCRYPTED;
360 return;
361 }
362
363 // We have an appropriate response, so move on normally.
364 bcmos_timer_stop(&hde_link->oam_timeout_timer);
365 hde_link->state = HDE_STATE_ENCRYPTED;
366}
367
368static void handle_waiting_for_oam_ack_disable_encryption(hde_link_data *hde_link, const bcmolt_msg *ind)
369{
370 hde_link->state = HDE_STATE_NOT_ENCRYPTED;
371}
372
373static void handle_ignore(hde_link_data *hde_link, const bcmolt_msg *ind)
374{
375 // Literally do nothing
376}
377
378static void handle_error(hde_link_data *hde_link, const bcmolt_msg *ind)
379{
380 BCM_LOG(ERROR, hde_data.log_id[hde_link->hde_link.device_id], "Unexpected event in state %s\n",
381 get_state_string(hde_link->state));
382}
383
384static link_state_handler link_state_machine[HDE_STATE__NUM_OF][HDE_EVENT__NUM_OF] =
385{
386 [HDE_STATE_NOT_ENCRYPTED] =
387 {
388 [HDE_EVENT_ENABLE_ENCRYPTION] = handle_not_encrypted_enable_encryption,
389 [HDE_EVENT_DISABLE_ENCRYPTION] = handle_error,
390 [HDE_EVENT_FRAME_RX] = handle_ignore,
391 [HDE_EVENT_OAM_TIMEOUT] = handle_ignore,
392 },
393 [HDE_STATE_ENCRYPTED] =
394 {
395 [HDE_EVENT_ENABLE_ENCRYPTION] = handle_error,
396 [HDE_EVENT_DISABLE_ENCRYPTION] = handle_encrypted_disable_encryption,
397 [HDE_EVENT_FRAME_RX] = handle_encrypted_frame_rx,
398 [HDE_EVENT_OAM_TIMEOUT] = handle_ignore,
399 },
400 [HDE_STATE_WAITING_FOR_OAM_ACK] =
401 {
402 [HDE_EVENT_ENABLE_ENCRYPTION] = handle_error,
403 [HDE_EVENT_DISABLE_ENCRYPTION] = handle_waiting_for_oam_ack_disable_encryption,
404 [HDE_EVENT_FRAME_RX] = handle_waiting_for_oam_ack_frame_rx,
405 [HDE_EVENT_OAM_TIMEOUT] = handle_waiting_for_oam_ack_oam_timeout,
406 }
407};
408
409static int32_t find_table_index(const hde_key *hde_link)
410{
411 uint16_t i;
412 for (i = 0; i < hde_data.num_links; ++i)
413 {
414 if (memcmp(hde_link, &hde_data.links[i], sizeof(*hde_link)) == 0)
415 {
416 return i;
417 }
418 }
419 return -1;
420}
421
422static void remove_link_from_table(int32_t link_index)
423{
424 int32_t i;
425 for (i = link_index; i < hde_data.num_links - 1; ++i)
426 {
427 /* Backwards copy all data expect for the timer handle */
428 hde_data.links[i].hde_link = hde_data.links[i + 1].hde_link;
429 hde_data.links[i].link_rate = hde_data.links[i + 1].link_rate;
430 hde_data.links[i].llid = hde_data.links[i + 1].llid;
431 hde_data.links[i].state = hde_data.links[i + 1].state;
432 }
433 /* also clear the state of the now empty link */
434 hde_data.links[hde_data.num_links - 1].state = HDE_STATE_NOT_ENCRYPTED;
435 hde_data.num_links--;
436}
437
438static void run_state_machine(int32_t link_index, const hde_task_msg *task_msg)
439{
440 if (link_index < 0) // We don't know of this link yet.
441 {
442 if (hde_data.num_links == HDE_MAX_NUM_LINKS)
443 {
444 BCM_LOG(ERROR, hde_data.log_id[task_msg->key.device_id], "Failure - Cannot add any more links!.\n");
445 return;
446 }
447
448 link_index = hde_data.num_links;
449 hde_data.links[link_index].hde_link = task_msg->key;
450 link_state_machine[hde_data.links[link_index].state][task_msg->event](&hde_data.links[link_index], task_msg->rx);
451
452 if (hde_data.links[link_index].state != HDE_STATE_NOT_ENCRYPTED)
453 {
454 // This link did not end in the state 'not encrypted', so we need to start tracking him.
455 ++hde_data.num_links;
456 }
457 }
458 else // We already know of this link.
459 {
460 link_state_machine[hde_data.links[link_index].state][task_msg->event](&hde_data.links[link_index], task_msg->rx);
461
462 if (hde_data.links[link_index].state == HDE_STATE_NOT_ENCRYPTED)
463 {
464 // The link has is no longer encrypted so lets forget about him.
465 remove_link_from_table(link_index);
466 }
467 }
468}
469
470static void hde_handle_event(bcmos_module_id module_id, bcmos_msg *os_msg)
471{
472 hde_task_msg *task_msg = (hde_task_msg *) os_msg;
473
474 int32_t link_index;
475
476 link_index = find_table_index(&task_msg->key);
477 run_state_machine(link_index, task_msg);
478
479 if (task_msg->rx != NULL)
480 {
481 bcmolt_msg_free(task_msg->rx);
482 }
483 bcmos_free(task_msg);
484}
485
486static bcmos_timer_rc oam_response_timeout(bcmos_timer *timer, long data)
487{
488 hde_task_msg *task_msg = bcmos_calloc(sizeof(*task_msg));
489
490 BUG_UNLESS(task_msg);
491
492 task_msg->key = hde_data.links[data].hde_link;
493 task_msg->event = HDE_EVENT_OAM_TIMEOUT;
494 task_msg->os_msg.handler = hde_handle_event;
495
496 bcmos_msg_send_to_module(BCMOS_MODULE_ID_USER_APPL_EPON_HDE, &task_msg->os_msg, BCMOS_MSG_SEND_AUTO_FREE);
497 return BCMOS_TIMER_OK;
498}
499
500static bcmos_errno hde_set_encryption(hde_key* key, bcmos_bool enabled)
501{
502 bcmos_errno rc = BCM_ERR_OK;
503
504 hde_task_msg *task_msg = bcmos_calloc(sizeof(*task_msg));
505
506 BUG_UNLESS(task_msg);
507
508 task_msg->key = *key;
509 task_msg->event = enabled ? HDE_EVENT_ENABLE_ENCRYPTION : HDE_EVENT_DISABLE_ENCRYPTION;
510 task_msg->os_msg.handler = hde_handle_event;
511
512 rc = bcmos_msg_send_to_module(BCMOS_MODULE_ID_USER_APPL_EPON_HDE, &task_msg->os_msg, BCMOS_MSG_SEND_AUTO_FREE);
513 BUG_ON(rc != BCM_ERR_OK);
514 return rc;
515}
516
517static bcmos_errno hde_cli_enable(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
518{
519 bcmos_errno rc = BCM_ERR_OK;
520 hde_key key =
521 {
522 .device_id = current_device,
523 .epon_ni = (bcmolt_epon_ni)(bcmcli_find_named_parm(session, "epon_ni")->value.number),
524 .mac_addr = (bcmos_mac_address)(bcmcli_find_named_parm(session, "mac_address")->value.mac)
525 };
526
527 rc = set_pon_encryption_if_needed(&key);
528 if (rc != BCM_ERR_OK)
529 {
530 return rc;
531 }
532 return hde_set_encryption(&key, BCMOS_TRUE);
533}
534
535static bcmos_errno hde_cli_disable(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
536{
537 hde_key key =
538 {
539 .device_id = current_device,
540 .epon_ni = (bcmolt_epon_ni)(bcmcli_find_named_parm(session, "epon_ni")->value.number),
541 .mac_addr = (bcmos_mac_address)(bcmcli_find_named_parm(session, "mac_address")->value.mac)
542 };
543
544 return hde_set_encryption(&key, BCMOS_FALSE);
545}
546
547// public indication handler interface -- called in transport layer context
548bcmos_errno bcmolt_epon_hde_process_rx(bcmolt_devid device_id, uint8_t instance, bcmolt_proxy_rx *rx)
549{
550 bcmos_errno rc = BCM_ERR_OK;
551 bcmolt_epon_link_frame_captured* actual_rx;
552 hde_task_msg *task_msg;
553 hde_key key;
554
555 if (!is_running)
556 {
557 return BCM_ERR_OK;
558 }
559
560 // We only look at message targetting epon links.
561 if (rx->hdr.obj_type != BCMOLT_OBJ_ID_EPON_LINK)
562 {
563 // Not an error, we just don't care about this object.
564 return BCM_ERR_OK;
565 }
566
567 // This is the only kind of proxy RX currently supported.
568 if (rx->hdr.subgroup != BCMOLT_EPON_LINK_PROXY_RX_ID_FRAME_CAPTURED)
569 {
570 return BCM_ERR_OK;
571 }
572
573 // This is safe due to the above subgroup check.
574 actual_rx = (bcmolt_epon_link_frame_captured*) rx;
575 key.device_id = device_id;
576 key.epon_ni = instance;
577 key.mac_addr = actual_rx->key.mac_address;
578
579 task_msg = bcmos_calloc(sizeof(*task_msg));
580 if (task_msg == NULL)
581 {
582 rc = BCM_ERR_NOMEM;
583 }
584 else
585 {
586 bcmolt_msg *rx_clone = NULL;
587 rc = bcmolt_msg_clone(&rx_clone, &rx->hdr);
588 if (rc != BCM_ERR_OK)
589 {
590 bcmos_free(task_msg);
591 return rc;
592 }
593 actual_rx = (bcmolt_epon_link_frame_captured*) rx_clone;
594
595 task_msg->rx = rx_clone;
596 task_msg->key = key;
597 task_msg->event = HDE_EVENT_FRAME_RX;
598 task_msg->os_msg.handler = hde_handle_event;
599 rc = bcmos_msg_send_to_module(BCMOS_MODULE_ID_USER_APPL_EPON_HDE, &task_msg->os_msg, BCMOS_MSG_SEND_AUTO_FREE);
600 if (rc != BCM_ERR_OK)
601 {
602 BCM_LOG(ERROR, hde_data.log_id[device_id], "Message send failed!\n");
603 bcmolt_msg_free(rx_clone);
604 }
605 }
606
607 return rc;
608}
609
610void bcmolt_epon_hde_appl_cli_init(bcmcli_entry *top_dir)
611{
612 static const char *dir_name = "hde";
613
614 if (bcmcli_dir_find(top_dir, dir_name))
615 {
616 return;
617 }
618
619 bcmcli_entry *dir = bcmcli_dir_add(top_dir, dir_name, "EPON OAM negotiation commands", BCMCLI_ACCESS_ADMIN, NULL);
620 BUG_ON(dir == NULL);
621
622 BCMCLI_MAKE_CMD(
623 dir,
624 "enable",
625 "Enable encryption for an EPON link",
626 hde_cli_enable,
627 BCMCLI_MAKE_PARM("epon_ni", "EPON NI", BCMCLI_PARM_NUMBER, 0),
628 BCMCLI_MAKE_PARM("mac_address", "MAC address", BCMCLI_PARM_MAC, 0));
629
630 BCMCLI_MAKE_CMD(
631 dir,
632 "disable",
633 "Disable encryption for an EPON link",
634 hde_cli_disable,
635 BCMCLI_MAKE_PARM("epon_ni", "EPON NI", BCMCLI_PARM_NUMBER, 0),
636 BCMCLI_MAKE_PARM("mac_address", "MAC address", BCMCLI_PARM_MAC, 0));
637}
638
639void bcmolt_epon_hde_appl_init(void)
640{
641 bcmos_errno rc = BCM_ERR_OK;
642 uint32_t i;
643
644 bcmos_task_parm task_params =
645 {
646 .name = "user_appl_hde",
647 .priority = TASK_PRIORITY_USER_APPL_EPON_HDE,
648 .core = BCMOS_CPU_CORE_ANY, /* No CPU affinity */
649 .init_handler = NULL
650 };
651
652 bcmos_timer_parm timer_parm =
653 {
654 .name = "oam_timeout_timer",
655 .owner = BCMOS_MODULE_ID_NONE,
656 .periodic = BCMOS_FALSE,
657 .handler = oam_response_timeout
658 };
659
660 if (is_running)
661 {
662 return;
663 }
664
665 is_running = BCMOS_TRUE;
666
667 for (i=0; i<BCMTR_MAX_OLTS; i++)
668 {
669 char log_name[MAX_DEV_LOG_ID_NAME];
670 snprintf(log_name, sizeof(log_name)-1, "user_appl_hde_%d", i);
671 hde_data.log_id[i] = bcm_dev_log_id_register(log_name, DEV_LOG_LEVEL_ERROR, DEV_LOG_ID_TYPE_BOTH);
672 }
673
674 hde_data.links = bcmos_calloc(HDE_MAX_NUM_LINKS * sizeof(hde_data.links[0]));
675 BUG_ON(hde_data.links == NULL);
676
677 rc = bcmos_task_create(&hde_data.task, &task_params);
678 BUG_ON(rc != BCM_ERR_OK);
679
680 bcmos_module_parm module_params =
681 {
682 .qparm = { .name = "user_appl_hde", .size = HDE_TASK_MSG_Q_SIZE }
683 };
684 rc = bcmos_module_create(BCMOS_MODULE_ID_USER_APPL_EPON_HDE, &hde_data.task, &module_params);
685 BUG_ON(rc != BCM_ERR_OK);
686
687 for (i = 0; i < HDE_MAX_NUM_LINKS; ++i)
688 {
689 timer_parm.data = i;
690 rc = bcmos_timer_create(&hde_data.links[i].oam_timeout_timer, &timer_parm);
691 BUG_ON(rc != BCM_ERR_OK);
692 }
693}