blob: 768c8b9c4c8f355f17d26c14c0804d5098325f4f [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
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with 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
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28*/
29
30/* This file contains the pieces of the OAM negotiation state machine that are specific to CTC OAM. */
31
32#include "bcmolt_eon_private.h"
33#include "../oam_common.h"
34#include "ctc.h"
35
36#define CTC_EXTENSION_SUPPORT 0x1
37#define CTC_PREFERRED_VERSION 0x30
38
39typedef enum
40{
41 CTC_NEG_ADVERTISING,
42 CTC_NEG_CONFIRMING,
43 CTC_NEG_DONE
44} ctc_neg_state;
45
46typedef struct
47{
48 ctc_neg_state state;
49 uint8_t selected_version;
50} ctc_state;
51
52static bcmolt_epon_oam_ctc_oui_version_pair ctc_advertised_versions[] =
53{
54 { .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC, .version = 0x30 },
55 { .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC, .version = 0x21 },
56 { .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC, .version = 0x20 },
57 { .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC, .version = 0x13 },
58 { .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC, .version = 0x01 }
59};
60
61/* Org specific TLV to send to the ONU */
62static const bcmolt_epon_oam_organization_specific_info ctc_tx_advertise_tlv =
63{
64 .oui = BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC,
65 .u =
66 {
67 .ctc =
68 {
69 .extension_support = CTC_EXTENSION_SUPPORT,
70 .version = CTC_PREFERRED_VERSION,
71 .supp_version_count = NUM_ELEM(ctc_advertised_versions),
72 .supp_version = ctc_advertised_versions
73 }
74 }
75};
76
77void ctc_tx_add_tlv(eon_link_state *link_state, bcmolt_epon_oam_oam_pdu_content *oam)
78{
79 ctc_state *ctc = link_state->org_spec_state;
80
81 if (ctc != NULL)
82 {
83 switch (ctc->state)
84 {
85 case CTC_NEG_ADVERTISING:
86 oam->u.info.tlvs[oam->u.info.tlvs_count].type = BCMOLT_EPON_OAM_INFO_TLV_TYPE_ORGANIZATION_SPECIFIC;
87 oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value = ctc_tx_advertise_tlv;
88 oam->u.info.tlvs_count++;
89 break;
90 case CTC_NEG_CONFIRMING:
91 oam->u.info.tlvs[oam->u.info.tlvs_count].type = BCMOLT_EPON_OAM_INFO_TLV_TYPE_ORGANIZATION_SPECIFIC;
92 oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value.oui =
93 BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC;
94 oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value.u.ctc.extension_support =
95 CTC_EXTENSION_SUPPORT;
96 oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value.u.ctc.version =
97 ctc->selected_version;
98 oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value.u.ctc.supp_version_count = 0;
99 oam->u.info.tlvs[oam->u.info.tlvs_count].u.organization_specific.value.u.ctc.supp_version = NULL;
100 oam->u.info.tlvs_count++;
101 break;
102 case CTC_NEG_DONE:
103 break; /* don't add a TLV */
104 default:
105 EON_LINK_LOG(ERROR, &link_state->link_key, "Unknown CTC state %d\n", ctc->state);
106 break;
107 }
108 }
109}
110
111void ctc_rx_tlv(
112 eon_link_state *link_state,
113 bcmolt_epon_oam_organization_specific_info *org_spec,
114 bcmos_errno *rc)
115{
116 *rc = BCM_ERR_IN_PROGRESS;
117
118 if (link_state->org_spec_state != NULL)
119 {
120 ctc_state *ctc = link_state->org_spec_state;
121
122 switch (ctc->state)
123 {
124 case CTC_NEG_ADVERTISING:
125 if ((NULL == org_spec) || (BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC != org_spec->oui))
126 {
127 EON_LINK_LOG(INFO, &link_state->link_key, "Didn't get CTC advertise TLV\n");
128 *rc = BCM_ERR_ONU_ERR_RESP;
129 }
130 else
131 {
132 /* find highest common version */
133 ctc->selected_version = 0;
134 for (uint8_t i = 0; i < org_spec->u.ctc.supp_version_count; i++)
135 {
136 for (uint8_t j = 0; j < NUM_ELEM(ctc_advertised_versions); j++)
137 {
138 if ((org_spec->u.ctc.supp_version[i].oui == ctc_advertised_versions[j].oui) &&
139 (org_spec->u.ctc.supp_version[i].version == ctc_advertised_versions[j].version))
140 {
141 if (ctc_advertised_versions[j].version > ctc->selected_version)
142 {
143 ctc->selected_version = ctc_advertised_versions[j].version;
144 }
145 }
146 }
147 }
148 if (ctc->selected_version == 0)
149 {
150 *rc = BCM_ERR_NOT_SUPPORTED; /* no common version found */
151 }
152 else
153 {
154 ctc->state = CTC_NEG_CONFIRMING;
155 }
156 }
157 break;
158 case CTC_NEG_CONFIRMING:
159 if ((NULL == org_spec) || (BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC != org_spec->oui))
160 {
161 EON_LINK_LOG(INFO, &link_state->link_key, "Didn't get CTC confirm TLV\n");
162 *rc = BCM_ERR_ONU_ERR_RESP;
163 }
164 else
165 {
166 if (org_spec->u.ctc.supp_version_count == 0)
167 {
168 if (org_spec->u.ctc.version != ctc->selected_version)
169 {
170 *rc = BCM_ERR_NOT_SUPPORTED;
171 }
172 else
173 {
174 ctc->state = CTC_NEG_DONE;
175 }
176 }
177 }
178 break;
179 case CTC_NEG_DONE:
180 if ((NULL != org_spec) && (org_spec->oui == BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC))
181 {
182 EON_LINK_LOG(
183 INFO, &link_state->link_key, "Got unexpected CTC TLV after negotiation\n");
184 *rc = BCM_ERR_ONU_ERR_RESP;
185 }
186 else
187 {
188 *rc = BCM_ERR_OK;
189 }
190 break;
191 default:
192 break;
193 }
194 }
195 else
196 {
197 if ((NULL != org_spec) && (org_spec->oui == BCMOLT_EPON_OAM_WELL_KNOWN_OUI_CTC))
198 {
199 EON_LINK_LOG(
200 INFO, &link_state->link_key, "Got unexpected CTC TLV before negotiation\n");
201 *rc = BCM_ERR_ONU_ERR_RESP;
202 }
203
204 if (LOCAL_STABLE_REMOTE_STABLE == link_state->oam_state)
205 {
206 ctc_state *ctc = bcmos_calloc(sizeof(ctc_state));
207 ctc->state = CTC_NEG_ADVERTISING;
208 link_state->org_spec_state = ctc;
209 }
210 }
211}
212