Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
IOPSYS
map-topology
Commits
01b5c40c
Commit
01b5c40c
authored
Nov 18, 2021
by
Stanislaw Gruszka
Browse files
map-topology: use cmdu_ackq from libieee1905
parent
f2e578ef
Pipeline
#35515
passed with stages
in 1 minute and 29 seconds
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/Makefile
View file @
01b5c40c
...
...
@@ -4,7 +4,7 @@ CFLAGS+=-I. -D_GNU_SOURCE
CFLAGS
+=
-g3
-Wall
-pthread
OBJS
=
main.o debug.o config.o json_utils.o nodes.o topo_ieee1905.o topologyd.o mdns_avahi.o
OBJS
+=
host_nodes.o host_config.o host_utils.o host.o
cmdu_ackq.o
timer.o
OBJS
+=
host_nodes.o host_config.o host_utils.o host.o timer.o
LIBS
=
-lubus
-lubox
-ljson-c
-lblobmsg_json
-luci
-pthread
-leasy
-lavahi-core
-lavahi-common
LIBS
+=
-lieee1905
-lmaputil
...
...
src/cmdu_ackq.c
deleted
100644 → 0
View file @
f2e578ef
/*
* delm_cmdu_ackq.c
* CMDU response and ack queue management
*
* Copyright (C) 2020 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
* See LICENSE file for license related information.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <libubus.h>
#include <libubox/utils.h>
#include <easy/easy.h>
#include "timer.h"
#include "cmdu_ackq.h"
#include "topologyd.h"
static
int
timeradd_msecs
(
struct
timeval
*
a
,
unsigned
long
msecs
,
struct
timeval
*
res
)
{
if
(
res
)
{
struct
timeval
t
=
{
0
};
if
(
msecs
>
1000
)
{
t
.
tv_sec
+=
msecs
/
1000
;
t
.
tv_usec
=
(
msecs
%
1000
)
*
1000
;
}
else
{
t
.
tv_usec
=
msecs
*
1000
;
}
timeradd
(
a
,
&
t
,
res
);
return
0
;
}
return
-
1
;
}
struct
cmdu_ackq_entry
*
cmdu_ackq_create_msg
(
uint16_t
type
,
uint16_t
mid
,
uint8_t
*
dest
,
uint32_t
timeout
)
{
struct
cmdu_ackq_entry
*
msg
;
struct
timeval
tsp
=
{
0
};
msg
=
calloc
(
1
,
sizeof
(
*
msg
));
if
(
!
msg
)
{
fprintf
(
stderr
,
"calloc failed. err = NOMEM
\n
"
);
return
NULL
;
}
msg
->
type
=
type
;
msg
->
mid
=
mid
;
gettimeofday
(
&
tsp
,
NULL
);
msg
->
ageing_time
=
timeout
;
timeradd_msecs
(
&
tsp
,
msg
->
ageing_time
,
&
msg
->
ageing_tmo
);
//msg->ageing_tmo.tv_usec = roundup(msg->ageing_tmo.tv_usec, 1000);
msg
->
ageing_tmo
.
tv_usec
=
(
msg
->
ageing_tmo
.
tv_usec
/
1000
)
*
1000
;
memcpy
(
msg
->
origin
,
dest
,
6
);
dbg
(
"CREATE msg: type = 0x%04x mid = %hu origin = "
MACFMT
" timeout = { %u (%lu:%lu) }
\n
"
,
type
,
mid
,
MAC2STR
(
dest
),
msg
->
ageing_time
,
msg
->
ageing_tmo
.
tv_sec
,
msg
->
ageing_tmo
.
tv_usec
/
1000
);
return
msg
;
}
static
void
cmdu_ackq_delete_msg
(
struct
cmdu_ackq_entry
*
msg
)
{
if
(
msg
)
free
(
msg
);
}
static
void
cmdu_ackq_ageout_entry
(
struct
cmdu_ackq
*
st
,
struct
hlist_head
*
head
,
struct
timeval
*
min_next_tmo
)
{
//struct delm_private *p = container_of(st,
// struct delm_private, cmdu_ack_q);
//struct wifi_network_device *dev = NULL;
struct
topologyd_private
*
p
=
container_of
(
st
,
struct
topologyd_private
,
cmdu_ack_q
);
struct
cmdu_ackq_entry
*
msg
;
struct
hlist_node
*
tmp
;
struct
timeval
now
=
{
0
};
gettimeofday
(
&
now
,
NULL
);
now
.
tv_usec
=
(
now
.
tv_usec
/
1000
)
*
1000
;
hlist_for_each_entry_safe
(
msg
,
tmp
,
head
,
hlist
)
{
dbg
(
"%s(): Entry msg->ageout = (%lu.%lu), now = (%lu.%lu)
\n
"
,
__func__
,
msg
->
ageing_tmo
.
tv_sec
,
msg
->
ageing_tmo
.
tv_usec
,
now
.
tv_sec
,
now
.
tv_usec
);
if
(
timercmp
(
&
msg
->
ageing_tmo
,
&
now
,
<=
))
{
st
->
pending_cnt
--
;
hlist_del
(
&
msg
->
hlist
,
head
);
dbg
(
"No response from "
MACFMT
" for CMDU 0x%x with mid = %hu
\n
"
,
MAC2STR
(
msg
->
origin
),
msg
->
type
,
msg
->
mid
);
/* mark the node as invalid node,
* reduce the pending count & update the datamodel
*/
dbg
(
"response timeout
\n
"
);
#if 0
dev = delm_get_origin_dev(p, msg->origin);
if (dev) {
/* TODO/REMOVE:
* mark the node as valid node to show the available data
*/
dev->is_valid_node = true;
//fprintf(stderr, "marking the node as invalid node: "
// MACFMT "\n", MAC2STR(dev->macaddr));
fprintf(stderr, "partial data has been received from this node: "
MACFMT "\n", MAC2STR(dev->macaddr));
if (p->pending <= 0)
delm_update_datamodel(p);
}
#endif
cmdu_ackq_delete_msg
(
msg
);
}
else
{
struct
timeval
new_next_tmo
=
{
0
};
timersub
(
&
msg
->
ageing_tmo
,
&
now
,
&
new_next_tmo
);
if
(
!
timercmp
(
min_next_tmo
,
&
new_next_tmo
,
<
))
{
min_next_tmo
->
tv_sec
=
new_next_tmo
.
tv_sec
;
min_next_tmo
->
tv_usec
=
new_next_tmo
.
tv_usec
;
/* fprintf("next-tmo = (%lu.%lu)\n",
* min_next_tmo->tv_sec,
* min_next_tmo->tv_usec);
*/
}
}
}
}
static
void
cmdu_ackq_ageing_timer_run
(
atimer_t
*
t
)
{
struct
cmdu_ackq
*
st
=
container_of
(
t
,
struct
cmdu_ackq
,
ageing_timer
);
//struct topologyd_private *p =
// container_of(t, struct topologyd_private, ageing_timer);
struct
timeval
min_next_tmo
=
{
.
tv_sec
=
999999
};
int
remain_cnt
=
0
;
int
i
;
struct
timeval
nu
;
gettimeofday
(
&
nu
,
NULL
);
dbg
(
"
\n
----Timer now = %lu.%lu --- cnt = %d---
\n
"
,
nu
.
tv_sec
,
nu
.
tv_usec
,
st
->
pending_cnt
);
//spin_lock(&st->hash_lock);
for
(
i
=
0
;
i
<
CMDU_BACKLOG_MAX
;
i
++
)
{
if
(
hlist_empty
(
&
st
->
table
[
i
]))
continue
;
//fprintf(stderr, "i = %d\t", i);
cmdu_ackq_ageout_entry
(
st
,
&
st
->
table
[
i
],
&
min_next_tmo
);
}
remain_cnt
=
st
->
pending_cnt
;
st
->
next_tmo
.
tv_sec
=
min_next_tmo
.
tv_sec
;
st
->
next_tmo
.
tv_usec
=
min_next_tmo
.
tv_usec
;
//spin_unlock(&st->hash_lock);
if
(
remain_cnt
)
{
uint32_t
tmo_msecs
=
st
->
next_tmo
.
tv_sec
*
1000
+
st
->
next_tmo
.
tv_usec
/
1000
;
/* printf("%s(): remain = %d next_tmo = {(%lu s, %lu us) %u}\n",
__func__, remain_cnt, next_tmo->tv_sec, next_tmo->tv_usec, tmo_msecs); */
if
(
tmo_msecs
>
0
)
timer_set
(
&
st
->
ageing_timer
,
tmo_msecs
);
}
}
int
cmdu_ackq_init
(
void
*
cmdu_q
)
{
struct
cmdu_ackq
*
q
=
(
struct
cmdu_ackq
*
)
cmdu_q
;
memset
(
q
,
0
,
sizeof
(
*
q
));
pthread_mutex_init
(
&
q
->
qlock
,
NULL
);
timer_init
(
&
q
->
ageing_timer
,
cmdu_ackq_ageing_timer_run
);
return
0
;
}
struct
cmdu_ackq_entry
*
cmdu_ackq_lookup
(
void
*
cmdu_q
,
uint16_t
type
,
uint16_t
mid
,
uint8_t
*
dest
)
{
struct
cmdu_ackq
*
q
=
(
struct
cmdu_ackq
*
)
cmdu_q
;
int
idx
=
cmdu_ackq_hash
(
type
,
mid
,
dest
);
struct
cmdu_ackq_entry
*
msg
=
NULL
;
pthread_mutex_lock
(
&
q
->
qlock
);
hlist_for_each_entry
(
msg
,
&
q
->
table
[
idx
],
hlist
)
{
if
(
msg
->
type
==
type
&&
msg
->
mid
==
mid
&&
!
memcmp
(
msg
->
origin
,
dest
,
6
))
{
pthread_mutex_unlock
(
&
q
->
qlock
);
return
msg
;
}
}
pthread_mutex_unlock
(
&
q
->
qlock
);
return
NULL
;
}
void
cmdu_ackq_reset
(
void
*
cmdu_q
)
{
struct
cmdu_ackq
*
q
=
(
struct
cmdu_ackq
*
)
cmdu_q
;
struct
cmdu_ackq_entry
*
msg
=
NULL
;
int
idx
=
0
;
dbg
(
"Resetting CMDU Message Queue..
\n
"
);
dbg
(
"*****************************************
\n
"
);
pthread_mutex_lock
(
&
q
->
qlock
);
for
(
idx
=
0
;
idx
<
CMDU_BACKLOG_MAX
;
idx
++
)
{
hlist_for_each_entry
(
msg
,
&
q
->
table
[
idx
],
hlist
)
{
dbg
(
"idx:%d, type:%d, mid:%d
\n
"
,
idx
,
msg
->
type
,
msg
->
mid
);
cmdu_ackq_delete_msg
(
msg
);
}
q
->
table
[
idx
].
first
=
NULL
;
}
dbg
(
"*****************************************
\n
"
);
q
->
pending_cnt
=
0
;
pthread_mutex_unlock
(
&
q
->
qlock
);
}
void
cmdu_ackq_free
(
void
*
cmdu_q
)
{
struct
cmdu_ackq
*
q
=
(
struct
cmdu_ackq
*
)
cmdu_q
;
cmdu_ackq_reset
(
q
);
timer_del
(
&
q
->
ageing_timer
);
pthread_mutex_destroy
(
&
q
->
qlock
);
}
/* In this function, type = cmdutype that is expected with 'mid' from 'dest' */
int
cmdu_ackq_enqueue
(
void
*
cmdu_q
,
uint16_t
type
,
uint16_t
mid
,
uint8_t
*
dest
,
uint32_t
timeout
)
{
struct
cmdu_ackq
*
q
=
(
struct
cmdu_ackq
*
)
cmdu_q
;
struct
cmdu_ackq_entry
*
msg
=
NULL
;
msg
=
cmdu_ackq_lookup
(
cmdu_q
,
type
,
mid
,
dest
);
if
(
msg
)
{
dbg
(
"Duplicate: type = 0x%04x mid = %hu origin = "
MACFMT
"
\n
"
,
type
,
mid
,
MAC2STR
(
dest
));
return
-
1
;
}
msg
=
cmdu_ackq_create_msg
(
type
,
mid
,
dest
,
timeout
);
if
(
msg
)
{
int
idx
=
cmdu_ackq_hash
(
type
,
mid
,
dest
);
pthread_mutex_lock
(
&
q
->
qlock
);
hlist_add_head
(
&
msg
->
hlist
,
&
q
->
table
[
idx
]);
q
->
pending_cnt
++
;
dbg
(
"ENQ: type = 0x%04x mid = %hu origin = "
MACFMT
"
\n
"
,
type
,
mid
,
MAC2STR
(
dest
));
if
(
timer_pending
(
&
q
->
ageing_timer
))
{
if
(
timercmp
(
&
q
->
next_tmo
,
&
msg
->
ageing_tmo
,
>
))
{
q
->
next_tmo
.
tv_sec
=
msg
->
ageing_tmo
.
tv_sec
;
q
->
next_tmo
.
tv_usec
=
msg
->
ageing_tmo
.
tv_usec
;
timer_set
(
&
q
->
ageing_timer
,
msg
->
ageing_time
);
dbg
(
"Adjust ageout timer ========>
\n
"
);
}
}
else
{
dbg
(
"Start ageout timer ========>
\n
"
);
q
->
next_tmo
.
tv_sec
=
msg
->
ageing_tmo
.
tv_sec
;
q
->
next_tmo
.
tv_usec
=
msg
->
ageing_tmo
.
tv_usec
;
timer_set
(
&
q
->
ageing_timer
,
msg
->
ageing_time
);
}
pthread_mutex_unlock
(
&
q
->
qlock
);
return
0
;
}
return
-
1
;
}
int
cmdu_ackq_dequeue
(
void
*
cmdu_q
,
uint16_t
type
,
uint16_t
mid
,
uint8_t
*
src
)
{
struct
cmdu_ackq
*
q
=
(
struct
cmdu_ackq
*
)
cmdu_q
;
struct
cmdu_ackq_entry
*
msg
=
NULL
;
int
idx
;
msg
=
cmdu_ackq_lookup
(
cmdu_q
,
type
,
mid
,
src
);
if
(
!
msg
)
{
dbg
(
"DROP! CMDU not found: type = 0x%04x mid = %hu origin = "
MACFMT
"
\n
"
,
type
,
mid
,
MAC2STR
(
src
));
return
-
1
;
}
idx
=
cmdu_ackq_hash
(
type
,
mid
,
src
);
pthread_mutex_lock
(
&
q
->
qlock
);
hlist_del
(
&
msg
->
hlist
,
&
q
->
table
[
idx
]);
q
->
pending_cnt
--
;
pthread_mutex_unlock
(
&
q
->
qlock
);
dbg
(
"DEQ: type = 0x%04x mid = %hu origin = "
MACFMT
"
\n
"
,
type
,
mid
,
MAC2STR
(
src
));
cmdu_ackq_delete_msg
(
msg
);
return
0
;
}
src/cmdu_ackq.h
deleted
100644 → 0
View file @
f2e578ef
/*
* cmdu_ackq.h
* CMDU pending response and ack queue management
*
* Copyright (C) 2020 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
* See LICENSE file for license related information.
*
*/
#ifndef CMDU_ACKQ_H
#define CMDU_ACKQ_H
#include <easy/easy.h>
#include <wifi.h>
#include "debug.h"
#define CMDU_BACKLOG_MAX 128
#define MAC_ADDR_HASH(a) (a[0] ^ a[1] ^ a[2] ^ a[3] ^ a[4] ^ a[5])
// TODO: improve hash func
#define cmdu_ackq_hash(t, m, o) \
((MAC_ADDR_HASH(o) ^ (t) ^ (m)) & (CMDU_BACKLOG_MAX - 1))
/* struct holds a pending cmdu with 'mid' from 'origin' */
struct
cmdu_ackq_entry
{
uint16_t
type
;
uint16_t
mid
;
uint8_t
origin
[
6
];
struct
hlist_node
hlist
;
uint32_t
ageing_time
;
/* in msecs */
struct
timeval
ageing_tmo
;
};
/* queue of cmdus for which response is pending */
struct
cmdu_ackq
{
pthread_mutex_t
qlock
;
/* hashtable of pending cmdu_ackq_entry */
struct
hlist_head
table
[
CMDU_BACKLOG_MAX
];
int
pending_cnt
;
atimer_t
ageing_timer
;
struct
timeval
next_tmo
;
};
extern
int
cmdu_ackq_init
(
void
*
q
);
extern
void
cmdu_ackq_free
(
void
*
q
);
extern
void
cmdu_ackq_reset
(
void
*
q
);
extern
int
cmdu_ackq_dequeue
(
void
*
q
,
uint16_t
type
,
uint16_t
mid
,
uint8_t
*
src
);
extern
int
cmdu_ackq_enqueue
(
void
*
q
,
uint16_t
type
,
uint16_t
mid
,
uint8_t
*
dest
,
uint32_t
timeout
);
#endif
/* CMDU_ACKQ_H */
src/topologyd.c
View file @
01b5c40c
...
...
@@ -224,7 +224,7 @@ void topologyd_event_handler(void *c, struct blob_attr *msg)
dbg
(
"Inside %s...DEQUEUE msg_type = [%d] msg_mid = [%d] src =["
MACFMT
"]
\n
"
,
__func__
,
msg_type
,
msg_mid
,
MAC2STR
(
origin
));
ret
=
cmdu_ackq_dequeue
(
&
priv
->
cmdu_ack_q
,
msg_type
,
msg_mid
,
origin
);
msg_mid
,
origin
,
NULL
);
if
(
ret
)
{
err
(
"topologyd: drop unexpected CMDU (mid = %d)
\n
"
,
msg_mid
);
...
...
@@ -2658,7 +2658,7 @@ uint16_t send_cmdu(struct topologyd_private *priv, struct cmdu_buff *cmdu, uint8
if
(
ret
!=
0
)
goto
out
;
cmdu_ackq_enqueue
(
&
priv
->
cmdu_ack_q
,
resp_type
,
msgid
,
dst
,
60000
);
dst
,
60000
,
0
,
NULL
);
dbg
(
"Inside %s...ENQUEUE msg_type = [%d] msg_mid = [%d] src =["
MACFMT
"]
\n
"
,
__func__
,
resp_type
,
msgid
,
MAC2STR
(
dst
));
ret
=
msgid
;
...
...
src/topologyd.h
View file @
01b5c40c
...
...
@@ -18,9 +18,9 @@
#include <1905_tlvs.h>
#include <map_module.h>
#include <map2.h>
#include <cmdu_ackq.h>
#include "host.h"
#include "cmdu_ackq.h"
#include "host_config.h"
#define IEEE1905_OBJECT "ieee1905"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment