mirror of
https://github.com/rtbrick/bngblaster.git
synced 2024-05-06 15:54:57 +00:00
Add basic EOAM CFM CC Support (experimental)
This commit is contained in:
+4
-2
@@ -187,8 +187,10 @@ Attribute | Description | Default
|
||||
`dhcp` | Optionally enable/disable DHCP per access configuration
|
||||
`dhcpv6` | Optionally enable/disable DHCPv6 per access configuration
|
||||
`stream-group-id` | Optional stream group identifier
|
||||
|
||||
**WARNING**: DHCP (IPv4) is currently not supported!
|
||||
`cfm-cc` | Optionally enable/disable EOAM CFM CC (IPoE only) | false
|
||||
`cfm-level` | Set EOAM CFM maintenance domain level | 0
|
||||
`cfm-ma-id` | Set EOAM CFM maintenance association identifier | 0
|
||||
`cfm-ma-name` | Set EOAM CFM maintenance association short name
|
||||
|
||||
For all modes it is possible to configure between zero and three VLAN
|
||||
tags on the access interface as shown below.
|
||||
|
||||
+11
-3
@@ -127,15 +127,19 @@ Attribute | Description
|
||||
`interfaces` | List all interfaces with index
|
||||
`session-counters` | Return session counters
|
||||
`terminate` | Terminate all sessions similar to sending SIGINT (ctr+c)
|
||||
`session-traffic` | Display session traffic statistics | |
|
||||
`session-traffic` | Display session traffic statistics
|
||||
`session-traffic-enabled` | Enable session traffic for all sessions
|
||||
`session-traffic-disabled` | Disable session traffic for all sessions
|
||||
`stream-traffic-enabled` | Enable stream traffic for all sessions | |
|
||||
`stream-traffic-disabled` | Disable stream traffic for all sessions | |
|
||||
`stream-traffic-enabled` | Enable stream traffic for all sessions
|
||||
`stream-traffic-disabled` | Disable stream traffic for all sessions
|
||||
`multicast-traffic-start` | Start sending multicast traffic from network interface
|
||||
`multicast-traffic-stop` | Stop sending multicast traffic from network interface
|
||||
`li-flows` | List all LI flows with detailed statistics
|
||||
`sessions-pending` | List all sessions not established
|
||||
`cfm-cc-start` | Start EOAM CFM CC
|
||||
`cfm-cc-stop` | Stop EOAM CFM CC
|
||||
`cfm-cc-rdi-on` | Set EOAM CFM CC RDI
|
||||
`cfm-cc-rdi-off` | Unset EOAM CFM CC RDI
|
||||
|
||||
### Session Commands
|
||||
|
||||
@@ -174,6 +178,10 @@ Attribute | Description | Mandatory Arguments | Optional Arguments
|
||||
`igmp-join` | Join group | `group` | `source1`, `source2`, `source3`
|
||||
`igmp-leave` | Leave group | `group` |
|
||||
`igmp-info` | IGMP information | |
|
||||
`cfm-cc-start` | Start EOAM CFM CC
|
||||
`cfm-cc-stop` | Stop EOAM CFM CC
|
||||
`cfm-cc-rdi-on` | Set EOAM CFM CC RDI
|
||||
`cfm-cc-rdi-off` | Unset EOAM CFM CC RDI
|
||||
|
||||
The `session-id` is the same as used for `{session-global}` in the
|
||||
configuration section. This number starts with 1 and is increased
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
#define BBL_SEND_ICMPV6_REPLY 0x00080000
|
||||
#define BBL_SEND_ICMPV6_NS 0x00100000
|
||||
#define BBL_SEND_ICMPV6_NA 0x00200000
|
||||
#define BBL_SEND_CFM_CC 0x00400000
|
||||
|
||||
/* Network Interface */
|
||||
#define BBL_IF_SEND_ARP_REQUEST 0x00000001
|
||||
@@ -252,6 +253,8 @@ typedef struct bbl_interface_
|
||||
/* Packet Stats */
|
||||
uint32_t arp_tx;
|
||||
uint32_t arp_rx;
|
||||
uint32_t cfm_cc_tx;
|
||||
uint32_t cfm_cc_rx;
|
||||
uint32_t padi_tx;
|
||||
uint32_t pado_rx;
|
||||
uint32_t padr_tx;
|
||||
@@ -342,55 +345,61 @@ typedef struct bbl_interface_
|
||||
|
||||
typedef struct bbl_access_config_
|
||||
{
|
||||
bool exhausted;
|
||||
uint32_t sessions; /* per access config session counter */
|
||||
struct bbl_interface_ *access_if;
|
||||
bool exhausted;
|
||||
uint32_t sessions; /* per access config session counter */
|
||||
struct bbl_interface_ *access_if;
|
||||
|
||||
char *interface;
|
||||
char *interface;
|
||||
|
||||
bbl_access_type_t access_type; /* pppoe or ipoe */
|
||||
bbl_vlan_mode_t vlan_mode; /* 1:1 (default) or N:1 */
|
||||
bbl_access_type_t access_type; /* pppoe or ipoe */
|
||||
bbl_vlan_mode_t vlan_mode; /* 1:1 (default) or N:1 */
|
||||
|
||||
uint16_t stream_group_id;
|
||||
uint16_t stream_group_id;
|
||||
|
||||
uint16_t access_outer_vlan;
|
||||
uint16_t access_outer_vlan_min;
|
||||
uint16_t access_outer_vlan_max;
|
||||
uint16_t access_inner_vlan;
|
||||
uint16_t access_inner_vlan_min;
|
||||
uint16_t access_inner_vlan_max;
|
||||
uint16_t access_third_vlan;
|
||||
uint16_t access_outer_vlan;
|
||||
uint16_t access_outer_vlan_min;
|
||||
uint16_t access_outer_vlan_max;
|
||||
uint16_t access_inner_vlan;
|
||||
uint16_t access_inner_vlan_min;
|
||||
uint16_t access_inner_vlan_max;
|
||||
uint16_t access_third_vlan;
|
||||
|
||||
/* Static */
|
||||
uint32_t static_ip;
|
||||
uint32_t static_ip_iter;
|
||||
uint32_t static_gateway;
|
||||
uint32_t static_gateway_iter;
|
||||
/* Static */
|
||||
uint32_t static_ip;
|
||||
uint32_t static_ip_iter;
|
||||
uint32_t static_gateway;
|
||||
uint32_t static_gateway_iter;
|
||||
|
||||
/* Authentication */
|
||||
char *username;
|
||||
char *password;
|
||||
uint16_t authentication_protocol;
|
||||
/* Authentication */
|
||||
char *username;
|
||||
char *password;
|
||||
uint16_t authentication_protocol;
|
||||
|
||||
/* Access Line */
|
||||
char *agent_remote_id;
|
||||
char *agent_circuit_id;
|
||||
uint32_t rate_up;
|
||||
uint32_t rate_down;
|
||||
uint32_t dsl_type;
|
||||
/* Access Line */
|
||||
char *agent_remote_id;
|
||||
char *agent_circuit_id;
|
||||
uint32_t rate_up;
|
||||
uint32_t rate_down;
|
||||
uint32_t dsl_type;
|
||||
|
||||
/* Protocols */
|
||||
bool ipcp_enable;
|
||||
bool ip6cp_enable;
|
||||
bool ipv4_enable;
|
||||
bool ipv6_enable;
|
||||
bool dhcp_enable;
|
||||
bool dhcpv6_enable;
|
||||
bool igmp_autostart;
|
||||
uint8_t igmp_version;
|
||||
bool session_traffic_autostart;
|
||||
/* Protocols */
|
||||
bool ipcp_enable;
|
||||
bool ip6cp_enable;
|
||||
bool ipv4_enable;
|
||||
bool ipv6_enable;
|
||||
bool dhcp_enable;
|
||||
bool dhcpv6_enable;
|
||||
bool igmp_autostart;
|
||||
uint8_t igmp_version;
|
||||
bool session_traffic_autostart;
|
||||
|
||||
void *next; /* pointer to next access config element */
|
||||
/* CFM CC */
|
||||
bool cfm_cc;
|
||||
uint8_t cfm_level;
|
||||
uint16_t cfm_ma_id;
|
||||
char *cfm_ma_name;
|
||||
|
||||
void *next; /* pointer to next access config element */
|
||||
} bbl_access_config_s;
|
||||
|
||||
/*
|
||||
@@ -745,6 +754,7 @@ typedef struct bbl_session_
|
||||
struct timer_ *timer_session_traffic_ipv6;
|
||||
struct timer_ *timer_session_traffic_ipv6pd;
|
||||
struct timer_ *timer_rate;
|
||||
struct timer_ *timer_cfm_cc;
|
||||
|
||||
bbl_access_type_t access_type;
|
||||
|
||||
@@ -782,6 +792,14 @@ typedef struct bbl_session_
|
||||
uint8_t server_mac[ETH_ADDR_LEN];
|
||||
uint8_t client_mac[ETH_ADDR_LEN];
|
||||
|
||||
/* CFM */
|
||||
bool cfm_cc;
|
||||
bool cfm_rdi;
|
||||
uint32_t cfm_seq;
|
||||
uint8_t cfm_level;
|
||||
uint16_t cfm_ma_id;
|
||||
char *cfm_ma_name;
|
||||
|
||||
/* PPPoE */
|
||||
uint16_t pppoe_session_id;
|
||||
uint8_t *pppoe_ac_cookie;
|
||||
|
||||
@@ -321,6 +321,30 @@ json_parse_access_interface (bbl_ctx_s *ctx, json_t *access_interface, bbl_acces
|
||||
if (value) {
|
||||
access_config->stream_group_id = json_number_value(value);
|
||||
}
|
||||
|
||||
value = json_object_get(access_interface, "cfm-cc");
|
||||
if (json_is_boolean(value)) {
|
||||
access_config->cfm_cc = json_boolean_value(value);
|
||||
}
|
||||
value = json_object_get(access_interface, "cfm-level");
|
||||
if (value) {
|
||||
access_config->cfm_level = json_number_value(value);
|
||||
if(access_config->cfm_level > 7) {
|
||||
fprintf(stderr, "JSON config error: Invalid value for access->cfm-level\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
value = json_object_get(access_interface, "cfm-ma-id");
|
||||
if (value) {
|
||||
access_config->cfm_ma_id = json_number_value(value);
|
||||
}
|
||||
if (json_unpack(access_interface, "{s:s}", "cfm-ma-name", &s) == 0) {
|
||||
access_config->cfm_ma_name = strdup(s);
|
||||
} else if (access_config->cfm_cc) {
|
||||
fprintf(stderr, "JSON config error: Missing access->cfm-ma-name\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1208,6 +1208,75 @@ bbl_ctrl_sessions_pending(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribut
|
||||
return result;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
bbl_ctrl_cfm_cc_start_stop(int fd, bbl_ctx_s *ctx, uint32_t session_id, bool status) {
|
||||
bbl_session_s *session;
|
||||
uint32_t i;
|
||||
if(session_id) {
|
||||
session = bbl_session_get(ctx, session_id);
|
||||
if(session) {
|
||||
session->cfm_cc = status;
|
||||
return bbl_ctrl_status(fd, "ok", 200, NULL);
|
||||
} else {
|
||||
return bbl_ctrl_status(fd, "warning", 404, "session not found");
|
||||
}
|
||||
} else {
|
||||
/* Iterate over all sessions */
|
||||
for(i = 0; i < ctx->sessions; i++) {
|
||||
session = ctx->session_list[i];
|
||||
if(session) {
|
||||
session->cfm_cc = status;
|
||||
}
|
||||
}
|
||||
return bbl_ctrl_status(fd, "ok", 200, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t
|
||||
bbl_ctrl_cfm_cc_start(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* arguments __attribute__((unused))) {
|
||||
return bbl_ctrl_cfm_cc_start_stop(fd, ctx, session_id, true);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
bbl_ctrl_cfm_cc_stop(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* arguments __attribute__((unused))) {
|
||||
return bbl_ctrl_cfm_cc_start_stop(fd, ctx, session_id, false);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
bbl_ctrl_cfm_cc_rdi(int fd, bbl_ctx_s *ctx, uint32_t session_id, bool status) {
|
||||
bbl_session_s *session;
|
||||
uint32_t i;
|
||||
if(session_id) {
|
||||
session = bbl_session_get(ctx, session_id);
|
||||
if(session) {
|
||||
session->cfm_rdi = status;
|
||||
return bbl_ctrl_status(fd, "ok", 200, NULL);
|
||||
} else {
|
||||
return bbl_ctrl_status(fd, "warning", 404, "session not found");
|
||||
}
|
||||
} else {
|
||||
/* Iterate over all sessions */
|
||||
for(i = 0; i < ctx->sessions; i++) {
|
||||
session = ctx->session_list[i];
|
||||
if(session) {
|
||||
session->cfm_rdi = status;
|
||||
}
|
||||
}
|
||||
return bbl_ctrl_status(fd, "ok", 200, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t
|
||||
bbl_ctrl_cfm_cc_rdi_on(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* arguments __attribute__((unused))) {
|
||||
return bbl_ctrl_cfm_cc_rdi(fd, ctx, session_id, true);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
bbl_ctrl_cfm_cc_rdi_off(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* arguments __attribute__((unused))) {
|
||||
return bbl_ctrl_cfm_cc_rdi(fd, ctx, session_id, false);
|
||||
}
|
||||
|
||||
|
||||
struct action {
|
||||
char *name;
|
||||
callback_function *fn;
|
||||
@@ -1242,6 +1311,10 @@ struct action actions[] = {
|
||||
{"stream-traffic-disabled", bbl_ctrl_stream_traffic_stop},
|
||||
{"stream-traffic-stop", bbl_ctrl_stream_traffic_stop},
|
||||
{"sessions-pending", bbl_ctrl_sessions_pending},
|
||||
{"cfm-cc-start", bbl_ctrl_cfm_cc_start},
|
||||
{"cfm-cc-stop", bbl_ctrl_cfm_cc_stop},
|
||||
{"cfm-cc-rdi-on", bbl_ctrl_cfm_cc_rdi_on},
|
||||
{"cfm-cc-rdi-off", bbl_ctrl_cfm_cc_rdi_off},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -1423,6 +1423,101 @@ encode_pppoe_session(uint8_t *buf, uint16_t *len,
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* encode_cfm
|
||||
*/
|
||||
protocol_error_t
|
||||
encode_cfm(uint8_t *buf, uint16_t *len, bbl_cfm_t *cfm) {
|
||||
|
||||
uint8_t max_ma_str_len = 45;
|
||||
|
||||
if(cfm->type != CFM_TYPE_CCM) {
|
||||
/* Currently only CFM CC is supported */
|
||||
return ENCODE_ERROR;
|
||||
}
|
||||
|
||||
*buf = cfm->md_level << 5; /* CFM MD level and version */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
*buf = cfm->type; /* CFM OpCode */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
|
||||
/* Set CFM CC interval fixed to 1s (4) */
|
||||
*buf = 4;
|
||||
if(cfm->rdi) {
|
||||
/* Set RDI bit */
|
||||
*buf |= 128;
|
||||
}
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
|
||||
/* Remember first TLV offset position */
|
||||
*buf = 70;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
memset(buf, 0x0, 70);
|
||||
|
||||
/* Sequence Number */
|
||||
*(uint32_t*)buf = htobe32(cfm->seq);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
|
||||
/* MA Identifier */
|
||||
*(uint16_t*)buf = htobe16(cfm->ma_id);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
|
||||
/* MD Name */
|
||||
*buf = cfm->md_name_format;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
if(cfm->md_name_format != CMF_MD_NAME_FORMAT_NONE) {
|
||||
if(cfm->md_name_len > 32) cfm->md_name_len = 32;
|
||||
*buf = cfm->md_name_len;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
memcpy(buf, cfm->md_name, cfm->md_name_len);
|
||||
BUMP_WRITE_BUFFER(buf, len, cfm->md_name_len);
|
||||
max_ma_str_len -= cfm->md_name_len + 1;
|
||||
}
|
||||
/* MA Name */
|
||||
*buf = cfm->ma_name_format;
|
||||
if(cfm->ma_name_len > max_ma_str_len) cfm->ma_name_len = max_ma_str_len;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
*buf = cfm->ma_name_len;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
memcpy(buf, cfm->ma_name, cfm->ma_name_len);
|
||||
BUMP_WRITE_BUFFER(buf, len, max_ma_str_len);
|
||||
|
||||
/* Y.1731 */
|
||||
BUMP_WRITE_BUFFER(buf, len, 16);
|
||||
|
||||
/* CFM TLVs */
|
||||
|
||||
/* Sender ID TLV */
|
||||
*buf = 1;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
*(uint16_t*)buf = htobe16(1);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*buf = 0;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
|
||||
/* Port Status TLV */
|
||||
*buf = 2;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
*(uint16_t*)buf = htobe16(1);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*buf = 2; /* UP */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
|
||||
/* Interface Status TLV */
|
||||
*buf = 4;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
*(uint16_t*)buf = htobe16(1);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*buf = 1; /* UP */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
|
||||
/* End TLV */
|
||||
*buf = 0;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
|
||||
return PROTOCOL_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* encode_ethernet
|
||||
*/
|
||||
@@ -1478,6 +1573,8 @@ encode_ethernet(uint8_t *buf, uint16_t *len,
|
||||
return encode_ipv4(buf, len, (bbl_ipv4_t*)eth->next);
|
||||
case ETH_TYPE_IPV6:
|
||||
return encode_ipv6(buf, len, (bbl_ipv6_t*)eth->next);
|
||||
case ETH_TYPE_CFM:
|
||||
return encode_cfm(buf, len, (bbl_cfm_t*)eth->next);
|
||||
default:
|
||||
return UNKNOWN_PROTOCOL;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#define ETH_TYPE_ARP 0x0806
|
||||
#define ETH_TYPE_IPV4 0x0800
|
||||
#define ETH_TYPE_IPV6 0x86dd
|
||||
#define ETH_TYPE_CFM 0x8902
|
||||
|
||||
#define ETH_ADDR_LEN 6
|
||||
#define ETH_VLAN_ID_MAX 4095
|
||||
@@ -204,6 +205,11 @@
|
||||
|
||||
#define QMX_LI_UDP_PORT 49152
|
||||
|
||||
#define CFM_TYPE_CCM 1
|
||||
#define CMF_MD_NAME_FORMAT_NONE 1
|
||||
#define CMF_MD_NAME_FORMAT_STRING 4
|
||||
#define CMF_MA_NAME_FORMAT_STRING 2
|
||||
|
||||
#define MAX_VLANS 3
|
||||
|
||||
#define BUMP_BUFFER(_buf, _len, _size) \
|
||||
@@ -798,6 +804,20 @@ typedef struct bbl_qmx_li_ {
|
||||
uint16_t payload_len; // LI payload length
|
||||
} bbl_qmx_li_t;
|
||||
|
||||
typedef struct bbl_cfm_ {
|
||||
uint8_t type;
|
||||
uint32_t seq;
|
||||
bool rdi;
|
||||
uint8_t md_level;
|
||||
uint8_t md_name_format;
|
||||
uint8_t md_name_len;
|
||||
uint8_t *md_name;
|
||||
uint16_t ma_id;
|
||||
uint8_t ma_name_format;
|
||||
uint8_t ma_name_len;
|
||||
uint8_t *ma_name;
|
||||
} bbl_cfm_t;
|
||||
|
||||
/*
|
||||
* decode_ethernet
|
||||
*/
|
||||
|
||||
@@ -389,6 +389,15 @@ bbl_rx_udp_ipv6(bbl_ethernet_header_t *eth, bbl_ipv6_t *ipv6, bbl_interface_s *i
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bbl_cfm_cc(timer_s *timer) {
|
||||
bbl_session_s *session = timer->data;
|
||||
if(session->session_state == BBL_ESTABLISHED && session->cfm_cc) {
|
||||
session->send_requests |= BBL_SEND_CFM_CC;
|
||||
bbl_session_network_tx_qnode_insert(session);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bbl_rx_established_ipoe(bbl_ethernet_header_t *eth, bbl_interface_s *interface, bbl_session_s *session) {
|
||||
|
||||
@@ -428,6 +437,10 @@ bbl_rx_established_ipoe(bbl_ethernet_header_t *eth, bbl_interface_s *interface,
|
||||
bbl_session_traffic_start_ipv6(ctx, session);
|
||||
bbl_session_traffic_start_ipv6pd(ctx, session);
|
||||
}
|
||||
if(session->cfm_cc) {
|
||||
/* Start CFM CC (currently fixed set to 1s) */
|
||||
timer_add_periodic(&ctx->timer_root, &session->timer_cfm_cc, "CFM-CC", 1, 0, session, &bbl_cfm_cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,6 +473,19 @@ bbl_sessions_init(bbl_ctx_s *ctx)
|
||||
session->agent_remote_id = strdup(s);
|
||||
}
|
||||
|
||||
/* Update CFM */
|
||||
if(access_config->cfm_cc) {
|
||||
session->cfm_cc = true;
|
||||
session->cfm_level = access_config->cfm_level;
|
||||
session->cfm_ma_id = access_config->cfm_ma_id;
|
||||
if(access_config->cfm_ma_name) {
|
||||
s = replace_substring(access_config->cfm_ma_name, "{session-global}", snum1);
|
||||
session->cfm_ma_name = s;
|
||||
s = replace_substring(session->cfm_ma_name, "{session}", snum2);
|
||||
session->cfm_ma_name = strdup(s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update access rates ... */
|
||||
session->rate_up = access_config->rate_up;
|
||||
session->rate_down = access_config->rate_down;
|
||||
|
||||
@@ -1488,6 +1488,31 @@ bbl_encode_packet_arp_reply (bbl_session_s *session)
|
||||
return encode_ethernet(session->write_buf, &session->write_idx, ð);
|
||||
}
|
||||
|
||||
protocol_error_t
|
||||
bbl_encode_packet_cfm_cc (bbl_session_s *session)
|
||||
{
|
||||
bbl_ethernet_header_t eth = {0};
|
||||
bbl_cfm_t cfm = {0};
|
||||
eth.dst = session->server_mac;
|
||||
eth.src = session->client_mac;
|
||||
eth.vlan_outer = session->vlan_key.outer_vlan_id;
|
||||
eth.vlan_inner = session->vlan_key.inner_vlan_id;
|
||||
eth.vlan_three = session->access_third_vlan;
|
||||
eth.type = ETH_TYPE_CFM;
|
||||
eth.next = &cfm;
|
||||
cfm.type = CFM_TYPE_CCM;
|
||||
cfm.seq = session->cfm_seq++;
|
||||
cfm.rdi = session->cfm_rdi;
|
||||
cfm.md_level = session->cfm_level;
|
||||
cfm.md_name_format = CMF_MD_NAME_FORMAT_NONE;
|
||||
cfm.ma_id = session->cfm_ma_id;
|
||||
cfm.ma_name_format = CMF_MA_NAME_FORMAT_STRING;
|
||||
cfm.ma_name_len = strlen(session->cfm_ma_name);
|
||||
cfm.ma_name = (uint8_t*)session->cfm_ma_name;
|
||||
session->interface->stats.cfm_cc_tx++;
|
||||
return encode_ethernet(session->write_buf, &session->write_idx, ð);
|
||||
}
|
||||
|
||||
protocol_error_t
|
||||
bbl_encode_packet (bbl_session_s *session, uint8_t *buf, uint16_t *len, bool *accounting)
|
||||
{
|
||||
@@ -1561,6 +1586,9 @@ bbl_encode_packet (bbl_session_s *session, uint8_t *buf, uint16_t *len, bool *ac
|
||||
} else if (session->send_requests & BBL_SEND_DHCP_REQUEST) {
|
||||
result = bbl_encode_packet_dhcp(session);
|
||||
session->send_requests &= ~BBL_SEND_DHCP_REQUEST;
|
||||
} else if (session->send_requests & BBL_SEND_CFM_CC) {
|
||||
result = bbl_encode_packet_cfm_cc(session);
|
||||
session->send_requests &= ~BBL_SEND_CFM_CC;
|
||||
} else {
|
||||
session->send_requests = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user