Skip to content
Snippets Groups Projects
Commit 70c9d070 authored by Maxim Menshikov's avatar Maxim Menshikov
Browse files

Installation of rules

parent 345d50d7
No related branches found
No related tags found
No related merge requests found
...@@ -10,45 +10,80 @@ ...@@ -10,45 +10,80 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <signal.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if_arp.h>
#include <linux/if_bridge.h>
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
#include <libubox/list.h> #include <json-c/json.h>
#include <libubox/blobmsg.h>
#include <libubox/blobmsg_json.h>
#include <libubox/uloop.h>
#include <libubox/ustream.h>
#include <libubox/utils.h>
#include <libubus.h>
#if (EASYMESH_VERSION >2)
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/ec.h>
#endif
#include <cmdu.h>
#include <1905_tlvs.h> #include <1905_tlvs.h>
#include <easymesh.h>
#include <i1905_wsc.h>
#include <map_module.h>
#include <uci.h>
#include "timer.h"
#include "utils/1905_ubus.h"
#include "utils/utils.h"
#include "utils/debug.h" #include "utils/debug.h"
#include "utils/liblist.h"
#include "steer_rules.h" #include "steer_rules.h"
#if (EASYMESH_VERSION > 2)
#include "dpp.h"
#endif
#include "config.h"
#include "nl.h"
#include "agent.h"
#include "qos.h"
#include "qos_internal.h"
/* Rule types */ void qos_rule_free(void *rule)
enum qos_rule_type {
QOS_RULE_TYPE_DSCP_PCP,
QOS_RULE_TYPE_MSCS,
QOS_RULE_TYPE_SCS,
QOS_RULE_TYPE_MGMT,
};
/* Temporary rule structure which contains both SPR and DSCP parts */
typedef struct temp_rule {
struct list_head list;
struct tlv_spr spr;
enum qos_rule_type type;
union {
struct ieee1905_dscp_pcp_usr dscp;
};
} temp_rule;
/* Rules list */
LIST_HEAD(rules);
int qos_add_dscp_rule(struct tlv_spr *spr, struct ieee1905_dscp_pcp_usr *dscp_pcp)
{ {
free(rule);
}
void qos_rule_free_all(struct list_head *list_head)
{
struct temp_rule *p, *tmp;
list_for_each_entry_safe(p, tmp, list_head, list) {
qos_rule_free(p);
}
}
int qos_add_dscp_rule(void *agent,
struct tlv_spr *spr,
struct ieee1905_dscp_pcp_usr *dscp_pcp)
{
struct agent *a = (struct agent *)agent;
struct temp_rule *r; struct temp_rule *r;
dbg("%s: adding DSCP rule...", __func__); dbg("%s: adding DSCP rule...\n", __func__);
list_for_each_entry(r, &rules, list) { list_for_each_entry(r, &a->qos_rules, list) {
if (r->spr.rule_id == spr->rule_id) { if (r->spr.rule_id == spr->rule_id) {
err("%s: adding DSCP rule exists", __func__); err("%s: DSCP rule exists\n", __func__);
return -1; return -1;
} }
} }
...@@ -62,19 +97,272 @@ int qos_add_dscp_rule(struct tlv_spr *spr, struct ieee1905_dscp_pcp_usr *dscp_pc ...@@ -62,19 +97,272 @@ int qos_add_dscp_rule(struct tlv_spr *spr, struct ieee1905_dscp_pcp_usr *dscp_pc
memcpy(&r->spr, spr, sizeof(struct tlv_spr)); memcpy(&r->spr, spr, sizeof(struct tlv_spr));
memcpy(&r->dscp, dscp_pcp, sizeof(struct ieee1905_dscp_pcp_usr)); memcpy(&r->dscp, dscp_pcp, sizeof(struct ieee1905_dscp_pcp_usr));
dbg("%s: DSCP rule added", __func__); dbg("%s: DSCP rule added\n", __func__);
list_add_tail(&r->list, &rules); list_add_tail(&r->list, &a->qos_rules);
return 0;
}
int qos_del_dscp_rule(void *agent,
struct tlv_spr *spr)
{
struct agent *a = (struct agent *)agent;
struct temp_rule *r;
dbg("%s: removing DSCP rule...\n", __func__);
list_for_each_entry(r, &a->qos_rules, list) {
if (r->spr.rule_id == spr->rule_id) {
list_del(&r->list);
dbg("%s: DSCP rule removed\n", __func__);
return 0;
}
}
err("%s: rule is not found\n", __func__);
return -1;
}
dscp_pcp_conv_result dscp_pcp2qosmap(uint8_t dscp_pcp[64],
char *qos_map,
size_t qos_map_len)
{
/* Internal constants */
#define PCP_COUNT (8)
#define DSCP_PCP_MAX (64)
#define DSCP_UP_EXC_MAX (21)
#define RANGE_MIN (0)
#define RANGE_MAX (1)
#define RANGE_TOTAL (2)
#define TMP_BUF_LEN (50)
#define DSCP_NEUTRAL (255)
dscp_pcp_conv_result rc = DSCP_PCP_CONV_RESULT_OK;
/* pcp -> dscp usage table */
uint8_t pcp_dscp[PCP_COUNT][DSCP_PCP_MAX];
/* Minimal and maximal DSCPs for PCP */
uint8_t pcp_dscp_min[PCP_COUNT] = { DSCP_NEUTRAL };
uint8_t pcp_dscp_max[PCP_COUNT] = { DSCP_NEUTRAL };
/* DSCP exceptions */
uint8_t dscp_up[DSCP_UP_EXC_MAX][2];
size_t total_du = 0;
size_t i, j;
size_t final_len;
memset(pcp_dscp, 0, sizeof(pcp_dscp));
/* Convert DSCP->PCP to PCP->DSCP usage table */
for (i = 0; i < DSCP_PCP_MAX; ++i)
{
uint8_t pcp = dscp_pcp[i];
uint8_t dscp = i;
pcp_dscp[pcp][dscp] = 1;
}
/* Find the biggest ranges of used DSCPs for PCPs */
for (i = 0; i < PCP_COUNT; ++i)
{
uint8_t ranges[64][3];
uint8_t total_ranges = 0;
int inside = 0;
uint8_t range_biggest_val;
int range_biggest_index = -1;
memset(ranges, 0, sizeof(ranges));
for (j = 0; j < DSCP_PCP_MAX; ++j)
{
if (pcp_dscp[i][j])
{
if (inside == 0)
{
inside = 1;
ranges[total_ranges][RANGE_MIN] = j;
ranges[total_ranges][RANGE_MAX] = j;
ranges[total_ranges][RANGE_TOTAL] = 1;
if (range_biggest_index == -1)
{
range_biggest_index = total_ranges;
range_biggest_val = 1;
}
total_ranges++;
}
else
{
ranges[total_ranges - 1][RANGE_MAX] = j;
ranges[total_ranges - 1][RANGE_TOTAL]++;
if (range_biggest_val <
ranges[total_ranges - 1][RANGE_TOTAL])
{
range_biggest_index = total_ranges - 1;
range_biggest_val++;
}
}
}
else
{
if (inside == 1)
{
inside = 0;
}
}
}
if (range_biggest_index != -1)
{
pcp_dscp_min[i] = ranges[range_biggest_index][RANGE_MIN];
pcp_dscp_max[i] = ranges[range_biggest_index][RANGE_MAX];
}
else
{
pcp_dscp_min[i] = DSCP_NEUTRAL;
pcp_dscp_max[i] = DSCP_NEUTRAL;
}
}
/* Find exceptions that don't belong to [DSCP_min, DSCP_max] range */
for (i = 0; i < DSCP_PCP_MAX; ++i)
{
uint8_t pcp = dscp_pcp[i];
uint8_t dscp = i;
if (dscp < pcp_dscp_min[pcp] ||
dscp > pcp_dscp_max[pcp])
{
dscp_up[total_du][0] = dscp;
dscp_up[total_du][1] = pcp;
total_du++;
if (total_du == DSCP_UP_EXC_MAX)
{
rc = DSCP_PCP_CONV_RESULT_OK_TOO_MANY_EXC;
break;
}
}
}
/* Write out pcp_X_dscp_min,pcp_X_dscp_max */
final_len = 0;
for (i = 0; i < total_du; ++i)
{
char pair[TMP_BUF_LEN];
/*
* No need for bounds check - result length can't exceed the buffer
* length
*/
sprintf(pair, "%d,%d,", dscp_up[i][0], dscp_up[i][1]);
final_len += strlen(pair);
if (final_len > qos_map_len)
{
rc = DSCP_PCP_CONV_RESULT_TOO_LONG;
break;
}
}
if (rc != DSCP_PCP_CONV_RESULT_OK &&
rc != DSCP_PCP_CONV_RESULT_OK_TOO_MANY_EXC)
return rc;
/* Write out PCP_x_DSCP_min, PCP_x_DSCP_max */
for (i = 0; i < PCP_COUNT; ++i)
{
char pair[TMP_BUF_LEN];
/*
* No need for bounds check - result length can't exceed the buffer
* length
*/
sprintf(pair, "%s%d,%d",
(i != 0 || total_du == 0) ? "," : "",
pcp_dscp_min[i],
pcp_dscp_max[i]);
final_len += strlen(pair);
if (final_len > qos_map_len)
{
rc = DSCP_PCP_CONV_RESULT_TOO_LONG;
break;
}
}
#undef PCP_COUNT
#undef DSCP_PCP_MAX
#undef DSCP_UP_EXC_MAX
#undef RANGE_MIN
#undef RANGE_MAX
#undef RANGE_TOTAL
#undef TMP_BUF_LEN
return rc;
}
int qos_apply_dscp_rules(void *agent)
{
dscp_pcp_conv_result rc;
struct agent *a = (struct agent *)agent;
struct temp_rule *r;
struct netif_fhcfg *fcfg = NULL;
dbg("%s: applying DSCP rules...\n", __func__);
list_for_each_entry(r, &a->qos_rules, list) {
char str[512] = { '\0' };
if (r->spr.output != 0x08)
continue;
rc = dscp_pcp2qosmap(r->dscp.dscp_pcp, str, sizeof(str) - 1);
if (rc != DSCP_PCP_CONV_RESULT_OK &&
rc != DSCP_PCP_CONV_RESULT_OK_TOO_MANY_EXC) {
err("%s: wrong QoS map\n", __func__);
continue;
}
list_for_each_entry(fcfg, &a->cfg.fhlist, list) {
runCmd("hostapd_cli -i %s set_qos_map_set %s",
fcfg->name, str);
}
dbg("%s: DSCP rule applied: %s\n", __func__, str);
}
qos_sync_rules_to_nodes(agent);
dbg("%s: done with DSCP rules\n", __func__);
return 0;
}
int qos_sync_rules_to_nodes(void *agent)
{
struct agent *a = (struct agent *)agent;
struct netif_fhcfg *fcfg = NULL;
struct node *n = NULL;
list_for_each_entry(n, &a->nodelist, list) {
char mac[50];
hwaddr_ntoa(n->alid, mac);
list_for_each_entry(fcfg, &a->cfg.fhlist, list) {
runCmd("hostapd_cli -i %s send_qos_map_conf %s",
fcfg->name, mac);
}
}
return 0; return 0;
} }
int qos_get_rules(void) int qos_get_rules(void *agent)
{ {
struct agent *a = (struct agent *)agent;
struct temp_rule *r; struct temp_rule *r;
int nr = 0; int nr = 0;
info("Registered QoS rules: "); info("Registered QoS rules:\n");
list_for_each_entry(r, &rules, list) { list_for_each_entry(r, &a->qos_rules, list) {
info("[%d] add %d prec %doutput %d always %d", info("[%d] add %d prec %doutput %d always %d\n",
r->spr.rule_id, r->spr.rule_id,
r->spr.add_remove, r->spr.add_remove,
r->spr.precedence, r->spr.precedence,
...@@ -82,7 +370,6 @@ int qos_get_rules(void) ...@@ -82,7 +370,6 @@ int qos_get_rules(void)
r->spr.always_match); r->spr.always_match);
nr++; nr++;
} }
info("\n");
return nr; return nr;
} }
...@@ -11,7 +11,15 @@ ...@@ -11,7 +11,15 @@
#include <libubox/list.h> #include <libubox/list.h>
#include <1905_tlvs.h> #include <1905_tlvs.h>
int qos_add_dscp_rule(struct tlv_spr *spr, struct ieee1905_dscp_pcp_usr *dscp_pcp); void qos_rule_free(void *rule);
int qos_get_rules(void); void qos_rule_free_all(struct list_head *list);
int qos_add_dscp_rule(void *a,
struct tlv_spr *spr,
struct ieee1905_dscp_pcp_usr *dscp_pcp);
int qos_del_dscp_rule(void *a,
struct tlv_spr *spr);
int qos_apply_dscp_rules(void *a);
int qos_sync_rules_to_nodes(void *agent);
int qos_get_rules(void *a);
#endif #endif
#ifndef MAPAGENT_QOS_INTERNAL_H
#define MAPAGENT_QOS_INTERNAL_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if_arp.h>
#include <linux/if_bridge.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <json-c/json.h>
#include <libubox/blobmsg.h>
#include <libubox/blobmsg_json.h>
#include <libubox/uloop.h>
#include <libubox/ustream.h>
#include <libubox/utils.h>
#include <libubus.h>
#if (EASYMESH_VERSION >2)
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/ec.h>
#endif
#include <cmdu.h>
#include <1905_tlvs.h>
#include <easymesh.h>
#include <i1905_wsc.h>
#include <map_module.h>
#include <uci.h>
#include "timer.h"
#include "utils/1905_ubus.h"
#include "utils/utils.h"
#include "utils/debug.h"
#include "utils/liblist.h"
#include "steer_rules.h"
#if (EASYMESH_VERSION > 2)
#include "dpp.h"
#endif
#include "config.h"
#include "nl.h"
#include "agent.h"
#include "qos.h"
/* Rule types */
enum qos_rule_type {
QOS_RULE_TYPE_DSCP_PCP,/**< DSCP policy type */
QOS_RULE_TYPE_MSCS, /**< MSCS rule */
QOS_RULE_TYPE_SCS, /**< SCS rule */
QOS_RULE_TYPE_MGMT, /**< Management rule */
};
/* Temporary rule structure which contains both SPR and DSCP parts */
typedef struct temp_rule {
struct list_head list; /**< List head */
struct tlv_spr spr; /**< Service Prioritization Rule */
enum qos_rule_type type; /**< Rule Type */
union {
struct ieee1905_dscp_pcp_usr dscp; /**< DSCP rule - valid only in
case of
QOS_RULE_TYPE_DSCP_PCP rule
type */
};
} temp_rule;
/* DSCP-PCP -> hostapd format conversion results */
typedef enum dscp_pcp_conv_result {
DSCP_PCP_CONV_RESULT_OK, /**< Conversion finished well */
DSCP_PCP_CONV_RESULT_OK_TOO_MANY_EXC, /**< Conversion finished well,
but too many exceptions */
DSCP_PCP_CONV_RESULT_TOO_LONG, /**< Too long result that didn't
fit the output buffer */
} dscp_pcp_conv_result;
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment