aboutsummaryrefslogtreecommitdiffstats
path: root/ctrl/facemgr
diff options
context:
space:
mode:
Diffstat (limited to 'ctrl/facemgr')
-rw-r--r--ctrl/facemgr/CMakeLists.txt19
-rw-r--r--ctrl/facemgr/cmake/Modules/Packaging.cmake15
-rw-r--r--ctrl/facemgr/config/facemgr.conf194
-rw-r--r--ctrl/facemgr/config/facemgr.service24
-rwxr-xr-xctrl/facemgr/config/post5
-rwxr-xr-xctrl/facemgr/config/postinst3
-rwxr-xr-xctrl/facemgr/config/prerm3
-rwxr-xr-xctrl/facemgr/config/preun3
-rw-r--r--ctrl/facemgr/examples/mobility/Makefile23
-rw-r--r--ctrl/facemgr/examples/mobility/mobility.c88
-rw-r--r--ctrl/facemgr/src/CMakeLists.txt8
-rw-r--r--ctrl/facemgr/src/api.c96
-rw-r--r--ctrl/facemgr/src/facelet.c6
-rw-r--r--ctrl/facemgr/src/interfaces/android_utility/android_utility.c6
-rw-r--r--ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c28
-rw-r--r--ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c146
-rw-r--r--ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h45
-rw-r--r--ctrl/facemgr/src/main.c2
18 files changed, 652 insertions, 62 deletions
diff --git a/ctrl/facemgr/CMakeLists.txt b/ctrl/facemgr/CMakeLists.txt
index 4290d9cd6..ba9de9464 100644
--- a/ctrl/facemgr/CMakeLists.txt
+++ b/ctrl/facemgr/CMakeLists.txt
@@ -42,8 +42,7 @@ if (NOT CMAKE_BUILD_TYPE)
endif()
if(CMAKE_BUILD_TYPE MATCHES Debug)
-message("IN DEBUG MODE")
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3")
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3")
endif()
set(CMAKE_MODULE_PATH
@@ -59,7 +58,7 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
-find_package_wrapper(Config REQUIRED)
+find_package_wrapper(Libconfig REQUIRED)
find_package_wrapper(LibEvent REQUIRED)
set(FACEMGR facemgr CACHE INTERNAL "" FORCE)
@@ -95,6 +94,20 @@ add_subdirectory(src)
include(Packaging)
+# Install service file in linux systems
+include(ServiceScript)
+install_service_script(
+ ${CMAKE_CURRENT_SOURCE_DIR}/config/facemgr.service
+ COMPONENT ${FACEMGR}
+)
+
+# Configuration file
+set(FACEMGR_CONF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/config/facemgr.conf)
+set(FACEMGR_CONF_FOLDER "/etc/facemgr")
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+ install (FILES ${FACEMGR_CONF_FILE} DESTINATION ${FACEMGR_CONF_FOLDER} COMPONENT ${FACEMGR})
+endif()
+
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
include(Packager)
make_packages()
diff --git a/ctrl/facemgr/cmake/Modules/Packaging.cmake b/ctrl/facemgr/cmake/Modules/Packaging.cmake
index 3a7e5a85c..bb4fa42fa 100644
--- a/ctrl/facemgr/cmake/Modules/Packaging.cmake
+++ b/ctrl/facemgr/cmake/Modules/Packaging.cmake
@@ -25,7 +25,22 @@ set(${FACEMGR}_DEB_DEPENDENCIES
CACHE STRING "Dependencies for deb/rpm package."
)
+set(${HICN_LIGHT}_DEB_PACKAGE_CONTROL_EXTRA
+ "${CMAKE_CURRENT_SOURCE_DIR}/config/postinst;${CMAKE_CURRENT_SOURCE_DIR}/config/prerm"
+ CACHE STRING "Control scripts conffiles, postinst, postrm, prerm."
+)
+
set(${FACEMGR}_RPM_DEPENDENCIES
"libconfig, libevent-devel, lib${LIBHICNCTRL} >= stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
+
+set(${HICN_LIGHT}_RPM_POST_INSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_SOURCE_DIR}/config/post"
+ CACHE STRING "Install script that will be copied in the %post section"
+)
+
+set(${HICN_LIGHT}_RPM_PRE_UNINSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_SOURCE_DIR}/config/preun"
+ CACHE STRING "Install script that will be copied in the %post section"
+)
diff --git a/ctrl/facemgr/config/facemgr.conf b/ctrl/facemgr/config/facemgr.conf
new file mode 100644
index 000000000..d9c6f5fa9
--- /dev/null
+++ b/ctrl/facemgr/config/facemgr.conf
@@ -0,0 +1,194 @@
+#
+# hICN facemgr configuration file
+#
+
+################################################################################
+# Global settings
+################################################################################
+
+global = {
+
+# Default type for face creation
+#
+# Values: "auto" | "native-udp" | "native-tcp" | "overlay-udp" | "overlay-tcp"
+# Default "auto"
+#
+#face_type = "auto";
+face_type = "overlay-udp"
+
+# Disable service discovery for overlay creation
+#
+# This is only meaningful for overlay_* face types. If service discovery is
+# disabled, only manually entered overlay information will be used, if any.
+# Otherwise, no face will be created.
+#
+# Values : true | false
+# Default: false
+#
+#disable_discovery = true;
+
+# Disable IPv4 face creation
+#
+# Values : true | false
+# Default: false
+#
+#disable_ipv4 = true;
+
+# Disable IPv6 face creation
+#
+# Values : true | false
+# Default: false
+#
+#disable_ipv6 = true;
+
+# overlay
+#
+# By default, no address is specified, and local and remote ports are set to
+# the standard value for hICN (9695).
+#
+
+};
+
+################################################################################
+# Per-interface rules
+################################################################################
+#
+# Rules allow to override the default behaviour of the face manager.
+#
+# The list of rules must be specified as follows (note that the last one has no
+# coma at the end) :
+#
+# rules = (
+# { ... },
+# { ... },
+# { ... }
+# );
+#
+# A rule is composed of match and override attributes, and has the following
+# syntax:
+#
+# {
+# match = {
+# interface_name = STRING;
+# interface_type = STRING;
+# };
+# override = {
+# face_type = STRING;
+# disable_discovery = BOOL;
+# ignore = BOOL;
+# tags = (STRING, STRING, STRING);
+# overlay = {
+# ipv4 = {
+# local_port = PORT;
+# remote_addr = IP_ADDRESS;
+# remote_port = PORT;
+# };
+# ipv6 = {
+# local_port = PORT;
+# remote_addr = IP_ADDRESS;
+# remote_port = PORT;
+# };
+# };
+# };
+# }
+#
+# Match attributes:
+#
+# Match attributes serve to identify rules and as such defining two rules with
+# similar matches is not allowed. However, overlapping match definitions are
+# possible, in which case only the first matching rule is considered.
+#
+# A match is composed of the name of an interface and/or its type (either
+# attribute is optional but at least one has to be specified).
+#
+# * interface_name - a string representing an interface name
+#
+# * interface_type - the type of interface to match
+#
+# Values: "wired" | "wifi" | "cellular"
+#
+# Override attributes:
+#
+# Those attributes are applied when all specified match attributes correspond,
+# and override general settings or default values.
+#
+# * face_type - type used for face creation
+#
+# Values: "auto" | "native_udp" | "native_tcp" | "overlay_udp" | "overlay_tcp"
+#
+# * disable_discovery - disable service discovery for overlay creation
+#
+# Values : true | false
+#
+# * ignore - a boolean indicating whether that interface should be ignored
+#
+# * TODO tags - a (possibly empty) list of tags to be associated to the created face.
+#
+# Values: "wired" | "wifi" | "cellular" | "trusted"
+#
+# * overlay
+#
+# An overlay specification is used to complement any information retrieved
+# through service discovery (or replace it if service discovery is
+# disabled).
+#
+# It is possible to specify values for IPv4, IPv6 or both.
+#
+# Note that it is not currently possible to set different settings for IPv4 and
+# IPv6 but overlay specifications.
+#
+#
+# Here are a few example of rule definitions:
+#
+# rules = (
+# # Ignore localhost interface
+# {
+# match = {
+# interface_name = "lo";
+# };
+# override = {
+# ignore = true;
+# };
+# },
+# # Set tags for unknown tunnnel interface
+# {
+# match = {
+# interface_name = "utun1";
+# };
+# override = {
+# tags = ("WIRED", "TRUSTED");
+# };
+# },
+# # Force cellular connections to use manually specified overlay faces
+# {
+# match = {
+# interface_type = "cellular",
+# };
+# override = {
+# overlay = {
+# ipv4 = {
+# local_port = 9695;
+# remote_addr = "10.60.16.14";
+# remote_port = 9695;
+# };
+# ipv6 = {
+# local_port = 9695;
+# remote_addr = "2001:420:44f1:10:20c:29ff:fef3:8f8f";
+# remote_port = 9695;
+# };
+# };
+# };
+# }
+# );
+#
+#rules = (
+#);
+
+################################################################################
+# Logging
+################################################################################
+
+log:
+{
+ log_level = "DEBUG";
+}
diff --git a/ctrl/facemgr/config/facemgr.service b/ctrl/facemgr/config/facemgr.service
new file mode 100644
index 000000000..0f9e818ea
--- /dev/null
+++ b/ctrl/facemgr/config/facemgr.service
@@ -0,0 +1,24 @@
+# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[Unit]
+Description=hICN face manager
+
+[Service]
+Environment=CONFIG=/etc/facemgr/facemgr.conf
+Environment=LOGFILE=/var/log/facemgr.log
+ExecStart=/usr/bin/facemgr -c ${CONFIG} 1>${LOGFILE} 2>&1
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/ctrl/facemgr/config/post b/ctrl/facemgr/config/post
new file mode 100755
index 000000000..7b2fd57fe
--- /dev/null
+++ b/ctrl/facemgr/config/post
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+if pidof systemd; then
+ systemctl enable facemgr
+fi
diff --git a/ctrl/facemgr/config/postinst b/ctrl/facemgr/config/postinst
new file mode 100755
index 000000000..4113b0eca
--- /dev/null
+++ b/ctrl/facemgr/config/postinst
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+systemctl enable facemgr
diff --git a/ctrl/facemgr/config/prerm b/ctrl/facemgr/config/prerm
new file mode 100755
index 000000000..b5c486ea5
--- /dev/null
+++ b/ctrl/facemgr/config/prerm
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+systemctl disable facemgr
diff --git a/ctrl/facemgr/config/preun b/ctrl/facemgr/config/preun
new file mode 100755
index 000000000..b5c486ea5
--- /dev/null
+++ b/ctrl/facemgr/config/preun
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+systemctl disable facemgr
diff --git a/ctrl/facemgr/examples/mobility/Makefile b/ctrl/facemgr/examples/mobility/Makefile
new file mode 100644
index 000000000..3b92d9d5f
--- /dev/null
+++ b/ctrl/facemgr/examples/mobility/Makefile
@@ -0,0 +1,23 @@
+EXEC = $(shell basename $$(pwd))
+CC = gcc
+
+CFLAGS = -std=gnu11 -O3 -Wall -Wextra -Wpedantic -Wstrict-aliasing
+
+SRC = $(wildcard *.c)
+OBJ = $(SRC:.c=.o)
+
+all: $(EXEC)
+
+${EXEC}: $(OBJ)
+ $(CC) -o $@ $^ $(LDFLAGS)
+
+%.o: %.c
+ $(CC) -o $@ -c $< $(CFLAGS)
+
+.PHONY: clean mrproper
+
+clean:
+ @rm -rf *.o
+
+mrproper: clean
+ @rm -rf $(EXEC)
diff --git a/ctrl/facemgr/examples/mobility/mobility.c b/ctrl/facemgr/examples/mobility/mobility.c
new file mode 100644
index 000000000..528951446
--- /dev/null
+++ b/ctrl/facemgr/examples/mobility/mobility.c
@@ -0,0 +1,88 @@
+/*
+ * Dummy server sending alternating bytes to all clients.
+ *
+ * This program can be used to trigger mobility events in the hICN forwarder, to
+ * switch from WiFi to LTE and back, at regular intervals.
+ *
+ * Test server using nc: nc -4kvul localhost 9533
+ */
+
+#include <arpa/inet.h> // inet_ntop
+#include <errno.h> // EINTR,. ..
+#include <netinet/in.h> // INET_ADDRSTRLEN, INET6_ADDRSTRLEN
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/timerfd.h>
+#include <sys/un.h> // sockaddr_un
+#include <unistd.h> // fcntl
+#include <fcntl.h> // fcntl
+
+#define MS2US(x) (x * 1000)
+
+/**
+ * \brief Main function
+ */
+int main(int argc, char **argv)
+{
+ int rc;
+
+ if (argc != 4) {
+ fprintf(stderr, "Usage: %s IP PORT INTERVAL\n", argv[0]);
+ fprintf(stderr, "\n");
+ fprintf(stderr, " IP Target hostname\n");
+ fprintf(stderr, " PORT Target port\n");
+ fprintf(stderr, " INTERVAL Interval between mobility events (in ms)\n");
+ fprintf(stderr, "\n");
+ exit(EXIT_FAILURE);
+ }
+
+ int interval = atoi(argv[3]);
+
+ int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ perror("socket");
+ goto ERR_SOCKET;
+ }
+
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr(argv[1]);
+ addr.sin_port = htons(atoi(argv[2]));
+
+ if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ perror("connect");
+ goto ERR_CONNECT;
+ }
+
+ unsigned state = 0;
+ char buf[1];
+ for(;;) {
+ usleep(MS2US(interval));
+
+ buf[0] = state;
+ rc = send(fd, buf, 1, 0);
+ if (rc < 0) {
+ if (errno == ECONNREFUSED) {
+ continue;
+ }
+ perror("send");
+ goto ERR_SEND;
+ }
+
+ state = 1 - state;
+ }
+
+ close(fd);
+
+ exit(EXIT_SUCCESS);
+
+ERR_SEND:
+ERR_CONNECT:
+ close(fd);
+ERR_SOCKET:
+ exit(EXIT_FAILURE);
+}
diff --git a/ctrl/facemgr/src/CMakeLists.txt b/ctrl/facemgr/src/CMakeLists.txt
index 4bcad475d..cf5606e04 100644
--- a/ctrl/facemgr/src/CMakeLists.txt
+++ b/ctrl/facemgr/src/CMakeLists.txt
@@ -64,10 +64,12 @@ set(LIBRARIES
m
${HICN_LIBRARIES}
${LIBHICNCTRL_LIBRARIES}
- ${CONFIG_LIBRARY}
+ ${LIBCONFIG_LIBRARIES}
${LIBEVENT_LIBRARY}
)
+set(FACEMGR_LIBRARY_LIST "${LIBCONFIG_LIBRARIES};${LIBEVENT_LIBRARY}" CACHE INTERNAL "FACEMGR_LIBRARY_LIST")
+
add_subdirectory(interfaces)
@@ -106,7 +108,7 @@ if (DISABLE_SHARED_LIBRARIES)
LINK_LIBRARIES ${LIBRARIES}
COMPONENT ${FACEMGR}
INCLUDE_DIRS ${INCLUDE_DIRS}
- INSTALL_ROOT_DIR hicn
+ HEADER_ROOT_DIR hicn
DEFINITIONS ${COMPILER_DEFINITIONS}
)
else ()
@@ -118,7 +120,7 @@ else ()
LINK_LIBRARIES ${LIBRARIES}
COMPONENT ${FACEMGR}
INCLUDE_DIRS ${INCLUDE_DIRS}
- INSTALL_ROOT_DIR hicn
+ HEADER_ROOT_DIR hicn
DEFINITIONS ${COMPILER_DEFINITIONS}
)
endif ()
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c
index 5d48e993f..b2e329e0a 100644
--- a/ctrl/facemgr/src/api.c
+++ b/ctrl/facemgr/src/api.c
@@ -21,12 +21,12 @@
#ifdef __ANDROID__
/*
- * Use AndroidUtility to determine interface types
+ * Use FacemgrUtility to determine interface types
*
* NOTE: this is currently disabled as SDK APIs do not allow to determine the
* type of interfaces that are DOWN
*/
-//#define WITH_ANDROID_UTILITY
+//#define WITH_FACEMGR_UTILITY
/*
* Use priority controller interface
@@ -34,6 +34,11 @@
#define WITH_PRIORITY_CONTROLLER
/*
+ * Dump facelets (debug)
+ */
+//#define WITH_DUMP
+
+/*
* Allow priority setting before interface is actually created
*/
#define WITH_DEFAULT_PRIORITIES
@@ -59,9 +64,11 @@
#include "interfaces/bonjour/bonjour.h"
#endif /* __linux__ */
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
#include "interfaces/android_utility/android_utility.h"
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
+
+#include "interfaces/priority_controller/priority_controller.h"
#include <hicn/face.h>
#include <hicn/facemgr/facelet.h>
@@ -100,9 +107,9 @@ extern interface_ops_t network_framework_ops;
extern interface_ops_t netlink_ops;
extern interface_ops_t bonjour_ops;
#endif
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
extern interface_ops_t android_utility_ops;
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
extern interface_ops_t priority_controller_ops;
#endif
@@ -162,9 +169,9 @@ struct facemgr_s {
interface_t * hl;
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
interface_t * au; /* android_utility */
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
interface_t * pc;
@@ -538,7 +545,7 @@ int facemgr_query_bonjour(facemgr_t * facemgr, netdevice_t * netdevice)
}
#endif /* __linux__ */
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
int facemgr_query_android_utility(facemgr_t * facemgr, netdevice_t netdevice)
{
/* Send an event to the interface */
@@ -564,7 +571,7 @@ ERR_ND:
ERR_MALLOC:
return -1;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
/**
@@ -640,7 +647,7 @@ facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
}
netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_ANDROID_UTILITY
+#ifndef WITH_FACEMGR_UTILITY
/*
* In addition to netdevice, netdevice_type should be present to correctly
* apply rules
@@ -650,7 +657,7 @@ facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from facelet");
return -2;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
/* Default ignore list */
if ((netdevice_type == NETDEVICE_TYPE_LOOPBACK) || (netdevice_type == NETDEVICE_TYPE_UNDEFINED)) {
@@ -705,7 +712,7 @@ facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
return 0;
}
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
/**
* \brief Complements facelet information through Android Utility interface
* \return 0 if request was successful, -1 in case of error, and -2 if the
@@ -741,7 +748,7 @@ facemgr_complement_facelet_au(facemgr_t * facemgr, facelet_t * facelet)
facelet_set_au_done(facelet);
return 0;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef __linux__
/**
@@ -763,7 +770,7 @@ facemgr_complement_facelet_bj(facemgr_t * facemgr, facelet_t * facelet)
}
netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_ANDROID_UTILITY
+#ifndef WITH_FACEMGR_UTILITY
/*
* In addition to netdevice, netdevice_type should be present to correctly
* apply rules
@@ -773,7 +780,7 @@ facemgr_complement_facelet_bj(facemgr_t * facemgr, facelet_t * facelet)
ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice_type from facelet");
return -2;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
bool discovery;
if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type,
@@ -835,7 +842,7 @@ facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet)
}
netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_ANDROID_UTILITY
+#ifndef WITH_FACEMGR_UTILITY
/*
* In addition to netdevice, netdevice_type should be present to correctly
* apply rules
@@ -845,7 +852,7 @@ facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet)
ERROR("[facemgr_complement_facelet_manual] Error retrieving netdevice_type from facelet");
return -2;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
int family = AF_UNSPEC;
if (facelet_has_family(facelet)) {
@@ -957,11 +964,11 @@ facemgr_complement_facelet(facemgr_t * facemgr, facelet_t * facelet)
if (!facelet_has_key(facelet))
return -2;
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
rc = facemgr_complement_facelet_au(facemgr, facelet);
if (rc != -2)
return rc;
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#if 0
if (!facelet_has_netdevice_type(facelet)) {
@@ -1008,7 +1015,7 @@ int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet)
}
netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_ANDROID_UTILITY
+#ifndef WITH_FACEMGR_UTILITY
/*
* In addition to netdevice, netdevice_type should be present to correctly
* apply rules
@@ -1018,7 +1025,7 @@ int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet)
ERROR("[facemgr_assign_face_type] Error retrieving netdevice_type from facelet");
return -2;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
if (facemgr_cfg_get_face_type(facemgr->cfg, &netdevice, netdevice_type, &face_type) < 0)
@@ -1153,9 +1160,9 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet)
facelet_unset_admin_state(facelet);
facelet_unset_state(facelet);
facelet_unset_bj_done(facelet);
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
facelet_unset_au_done(facelet);
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
facelet_set_status(facelet, FACELET_STATUS_DELETED);
#if 0
@@ -1416,9 +1423,9 @@ facemgr_consider_static_facelet(facemgr_t * facemgr, facelet_t * facelet)
facelet_unset_state(new_facelet);
facelet_unset_bj_done(new_facelet);
facelet_clear_routes(new_facelet);
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
facelet_unset_au_done(new_facelet);
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
/* We try to apply static_facelet over facelet */
if (!facelet_match(new_facelet, static_facelet)) {
@@ -1650,9 +1657,9 @@ facemgr_process_facelet_delete(facemgr_t * facemgr, facelet_t * facelet)
facelet_unset_admin_state(facelet);
facelet_unset_state(facelet);
facelet_unset_bj_done(facelet);
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
facelet_unset_au_done(facelet);
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
facelet_unset_error(facelet);
facelet_set_status(facelet, FACELET_STATUS_DELETED);
#if 0
@@ -1787,7 +1794,9 @@ int
facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
{
bool remove_facelet = true;
+#if WITH_DUMP
bool dump = true;
+#endif /* WITH_DUMP */
int ret = 0;
int rc;
assert(facelet_in);
@@ -1877,7 +1886,9 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
rc = facemgr_process_facelet_get(facemgr, facelet_in);
if (rc == 0)
remove_facelet = false;
+#if WITH_DUMP
dump = false;
+#endif
if (rc == -1) {
ERROR("[facemgr_on_event] Error processing GET event");
goto ERR;
@@ -1985,7 +1996,9 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
//DEBUG("[facemgr_on_event] GET EXISTING %s", facelet_old_s);
//DEBUG(" WITH %s", facelet_s);
//ERROR("[facemgr_on_event] GET event for a face that already exists...");
+#ifdef WITH_DUMP
dump = false;
+#endif /* WITH_DUMP */
continue;
case FACELET_EVENT_UPDATE:
@@ -2066,7 +2079,7 @@ ERR:
ret = -1;
DUMP_CACHE:
-#if 1
+#if WITH_DUMP
if (dump) {
DEBUG(" <CACHE>");
facelet_set_dump(facemgr->facelet_cache);
@@ -2074,7 +2087,7 @@ DUMP_CACHE:
DEBUG("</EVENT ret=%d>", ret);
DEBUG("----------------------------------");
}
-#endif
+#endif /* WITH_DUMP */
free(cached_facelets);
@@ -2188,13 +2201,13 @@ facemgr_bootstrap(facemgr_t * facemgr)
}
#endif /* __linux__ */
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
rc = interface_register(&android_utility_ops);
if (rc < 0) {
ERROR("[facemgr_bootstrap] Error registering android_utility interface");
goto ERR_REGISTER;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
INFO("[facemgr_bootstrap] registering priority_controller interface");
@@ -2245,7 +2258,7 @@ facemgr_bootstrap(facemgr_t * facemgr)
}
#endif /* __linux__ */
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
android_utility_cfg_t au_cfg = {
.jvm = facemgr->jvm,
};
@@ -2254,11 +2267,16 @@ facemgr_bootstrap(facemgr_t * facemgr)
ERROR("Error creating 'Android Utility' interface\n");
goto ERR_AU_CREATE;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
INFO("[facemgr_bootstrap] creating priority_controller interface");
- rc = facemgr_create_interface(facemgr, "pc", "priority_controller", NULL, &facemgr->pc);
+ priority_controller_cfg_t pc_cfg = {
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+ .jvm = facemgr->jvm,
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
+ };
+ rc = facemgr_create_interface(facemgr, "pc", "priority_controller", &pc_cfg, &facemgr->pc);
if (rc < 0) {
ERROR("Error creating 'Priority Controller' interface\n");
goto ERR_PC_CREATE;
@@ -2293,10 +2311,10 @@ ERR_UPDOWN_CREATE:
facemgr_delete_interface(facemgr, facemgr->dummy);
ERR_DUMMY_CREATE:
#endif
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
facemgr_delete_interface(facemgr, facemgr->au);
ERR_AU_CREATE:
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
facemgr_delete_interface(facemgr, facemgr->pc);
ERR_PC_CREATE:
@@ -2346,9 +2364,9 @@ void facemgr_stop(facemgr_t * facemgr)
}
#endif /* __linux__ */
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
facemgr_delete_interface(facemgr, facemgr->au);
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
facemgr_delete_interface(facemgr, facemgr->pc);
diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c
index 1958749ae..f51f5802b 100644
--- a/ctrl/facemgr/src/facelet.c
+++ b/ctrl/facemgr/src/facelet.c
@@ -356,8 +356,10 @@ facelet_create_from_face(face_t * face)
facelet->error = 0;
/* TODO Consistency check between face type and found attributes */
- if (facelet_validate_face(facelet) < 0)
+ if (facelet_validate_face(facelet) < 0) {
+ ERROR("[facelet_create_from_face] Cannot validate face");
goto ERR_FACE;
+ }
facelet->bj_done = false;
facelet->au_done = false;
@@ -367,7 +369,7 @@ facelet_create_from_face(face_t * face)
/* We need to get route set */
facelet->routes = route_set_create();
if (!facelet->routes) {
- ERROR("[facelet_create] Cannot create route set");
+ ERROR("[facelet_create_from_face] Cannot create route set");
goto ERR_ROUTE_SET;
}
facelet->routes_done = false;
diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
index 55468baf8..d8e20659a 100644
--- a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
+++ b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
@@ -20,15 +20,15 @@
#include <assert.h>
-#include <hicn/face.h>
#include <hicn/facemgr.h>
+#include <hicn/ctrl/face.h>
#include <hicn/util/log.h>
#include "../../common.h"
#include "../../interface.h"
#include "android_utility.h"
-#define FACEMGR_ANDROID_UTILITY_CLASS "com/cisco/hicn/forwarder/supportlibrary/AndroidUtility"
+#define FACEMGR_UTILITY_CLASS "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility"
#define AU_INTERFACE_TYPE_UNDEFINED 0
@@ -89,7 +89,7 @@ int au_on_event(interface_t * interface, facelet_t * facelet)
JNIEnv *env;
JavaVM *jvm = data->cfg.jvm;
(*jvm)->AttachCurrentThread(jvm, &env, NULL);
- jclass cls = (*env)->FindClass(env, FACEMGR_ANDROID_UTILITY_CLASS);
+ jclass cls = (*env)->FindClass(env, FACEMGR_UTILITY_CLASS);
jmethodID getNetworkType = (*env)->GetStaticMethodID(env, cls,
"getNetworkType", "(Ljava/lang/String;)I");
jint interface_type = (*env)->CallStaticIntMethod(env, cls, getNetworkType,
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
index 508c0713b..8d3e18cdb 100644
--- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
+++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
@@ -327,13 +327,12 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
switch(facelet_get_event(facelet)) {
case FACELET_EVENT_CREATE:
-
- /* Create face */
{
+ /* Create face */
char buf[MAXSZ_FACELET];
facelet_snprintf(buf, MAXSZ_FACELET, facelet);
DEBUG("Create facelet %s", buf);
- }
+
hc_face.face = *face;
rc = hc_face_create(data->s, &hc_face);
if (rc < 0) {
@@ -341,7 +340,8 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
goto ERR;
}
- INFO("Created face id=%d", hc_face.id);
+ INFO("Created face id=%d - %s", hc_face.id, buf);
+ }
hicn_route_t ** route_array;
int n = facelet_get_route_array(facelet, &route_array);
@@ -413,7 +413,6 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
case FACELET_EVENT_DELETE:
/* Removing a face should also remove associated routes */
- /* Create face */
hc_face.face = *face;
rc = hc_face_delete(data->s, &hc_face);
if (rc < 0) {
@@ -421,6 +420,11 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
goto ERR;
}
+
+ char buf[MAXSZ_FACELET];
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet);
+ INFO("Deleted face id=%d", hc_face.id);
+
break;
case FACELET_EVENT_UPDATE:
@@ -457,7 +461,8 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
goto ERR;
}
facelet_set_admin_state_status(facelet, FACELET_ATTR_STATUS_CLEAN);
- INFO("Admin state updated");
+ INFO("Updated face id=%d - admin_state=%s", hc_face.id,
+ face_state_str(admin_state));
}
#ifdef WITH_POLICY
if (facelet_get_netdevice_type_status(facelet) == FACELET_ATTR_STATUS_DIRTY) {
@@ -517,7 +522,8 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
goto ERR;
}
facelet_set_netdevice_type_status(facelet, FACELET_ATTR_STATUS_CLEAN);
- INFO("Tags updated");
+ INFO("Updated face id=%d - netdevice_type=%s", hc_face.id,
+ netdevice_type_str(netdevice_type));
}
if (facelet_get_priority_status(facelet) == FACELET_ATTR_STATUS_DIRTY) {
INFO("Updating priority...");
@@ -549,7 +555,8 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
goto ERR;
}
facelet_set_priority_status(facelet, FACELET_ATTR_STATUS_CLEAN);
- INFO("Priority updated");
+
+ INFO("Updated face id=%d - priority=%d", hc_face.id, priority);
}
#endif /* WITH_POLICY */
break;
@@ -642,6 +649,11 @@ int hl_callback(interface_t * interface, int fd, void * unused)
/* We can ignore faces on localhost */
facelet_t * facelet = facelet_create_from_face(&f->face);
+ if (!facelet) {
+ ERROR("[hl_callback] Could not create facelet... skipping");
+ continue;
+ }
+
foreach_route(r, data->polled_routes) {
if (r->face_id != f->id)
continue;
diff --git a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c
index 76538185f..67edc5e39 100644
--- a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c
+++ b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -27,19 +27,110 @@
#include <hicn/facemgr.h>
+#include "priority_controller.h"
#include "../../common.h"
#include "../../interface.h"
#define PC_DEFAULT_PORT 9533
typedef struct {
+ priority_controller_cfg_t cfg;
int fd;
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+ unsigned state;
+ JNIEnv * env;
+ jclass cls;
+ jmethodID mid;
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
} pc_data_t;
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+#include <jni.h>
+
+#define ERR_STR_JAVA "Java VM parameters are required in the interface configuration."
+
+#define PREFER_CELLULAR 0
+#define PREFER_WIFI 1
+#define PREFER_BOTH 2
+
+#define INTERVAL_MS 500
+
+const char * prefer_str[] = { "Cellular", "WiFi", "both" };
+
+jclass find_class_global(JNIEnv* env, const char *name){
+ jclass c = (*env)->FindClass(env, name);
+ jclass c_global = 0;
+ if (c){
+ c_global = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ }
+ return c_global;
+}
+
+
+int priority_controller_tick(interface_t * interface, int fd, void * unused)
+{
+ pc_data_t * data = (pc_data_t*)interface->data;
+ unsigned new_state = PREFER_BOTH;
+
+ jint rssi = (*data->env)->CallStaticIntMethod(data->env, data->cls, data->mid);
+ DEBUG("[priority_controller_tick] rssi=%d\n", rssi);
+ if (rssi > -67) {
+ new_state = PREFER_WIFI;
+
+#if 0
+ } else if ((rssi < -67) && (rssi > -70)) {
+ new_state = PREFER_BOTH;
+#endif
+
+ } else { /* rssi < -70 */
+ new_state = PREFER_CELLULAR;
+ }
+
+ if (new_state == data->state)
+ return 0;
+
+ ERROR("[priority_controller_tick] Setting priority to %s", prefer_str[new_state]);
+
+ /* XXX Factor this */
+
+ facelet_t * facelet_w = facelet_create();
+ facelet_t * facelet_c = facelet_create();
+ facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI);
+ facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR);
+ facelet_set_attr_clean(facelet_w);
+ facelet_set_attr_clean(facelet_c);
+
+ switch(new_state) {
+ case PREFER_CELLULAR:
+ facelet_set_priority(facelet_w, 0);
+ facelet_set_priority(facelet_c, 10);
+ break;
+ case PREFER_WIFI:
+ facelet_set_priority(facelet_w, 10);
+ facelet_set_priority(facelet_c, 0);
+ break;
+ case PREFER_BOTH:
+ facelet_set_priority(facelet_w, 0);
+ facelet_set_priority(facelet_c, 0);
+ break;
+ }
+
+ facelet_set_event(facelet_w, FACELET_EVENT_UPDATE);
+ facelet_set_event(facelet_c, FACELET_EVENT_UPDATE);
+
+ interface_raise_event(interface, facelet_w);
+ interface_raise_event(interface, facelet_c);
+
+ data->state = new_state;
+
+ return 0;
+}
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
+
int priority_controller_initialize(interface_t * interface, void * cfg)
{
INFO("Initializing priority controller");
- struct sockaddr_in addr;
pc_data_t * data = malloc(sizeof(pc_data_t));
if (!data) {
@@ -49,6 +140,33 @@ int priority_controller_initialize(interface_t * interface, void * cfg)
interface->data = data;
+ data->cfg = * (priority_controller_cfg_t *) cfg;
+
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+
+ if (!cfg) {
+ ERROR(ERR_STR_JAVA);
+ goto ERR_CFG;
+ }
+
+ /* Retrieve RSSI information from SDK through AndroidUtility class */
+ (*data->cfg.jvm)->AttachCurrentThread(data->cfg.jvm, &data->env, NULL);
+ data->cls = find_class_global(data->env, FACEMGR_ANDROID_UTILITY_CLASS);
+ if (data->cls == 0)
+ goto ERR_JAVA;
+ data->mid = (*data->env)->GetStaticMethodID(data->env, data->cls, "getWifiRSSI", "()I");
+
+ data->fd = interface_register_timer(interface, INTERVAL_MS,
+ priority_controller_tick, interface);
+ if (data->fd < 0) {
+ ERROR("[priority_controller_initialize] Could not initialize timer");
+ goto ERR_FD;
+ }
+ data->state = PREFER_BOTH;
+
+#else /* PRIORITY_CONTROLLER_INTERNAL */
+ struct sockaddr_in addr;
+
data->fd = socket(AF_INET, SOCK_DGRAM, 0);
//data->fd = socket(AF_INET, SOCK_STREAM, 0);
if (data->fd < 0) {
@@ -67,18 +185,28 @@ int priority_controller_initialize(interface_t * interface, void * cfg)
perror("bind error");
goto ERR_BIND;
}
+
+ DEBUG("[priority_controller_initialize] register fd");
if (interface_register_fd(interface, data->fd, NULL) < 0) {
ERROR("[priority_controller_initialize] Error registering fd");
goto ERR_FD;
}
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
+
INFO("Priority controller successfully initialized");
return 0;
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+ERR_CFG:
+ERR_JAVA:
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
ERR_FD:
+#ifndef PRIORITY_CONTROLLER_INTERNAL
ERR_BIND:
close(data->fd);
ERR_SOCKET:
+#endif /* ! PRIORITY_CONTROLLER_INTERNAL */
free(data);
ERR_MALLOC:
return -1;
@@ -88,12 +216,21 @@ int priority_controller_finalize(interface_t * interface)
{
pc_data_t * data = (pc_data_t*)interface->data;
- if (data->fd > 0) {close(data->fd);}
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+ DEBUG("[priority_controller_finalize] unregister timer");
+ interface_unregister_timer(interface, data->fd);
+#else
+ if (data->fd > 0) {
+ interface_unregister_fd(interface, data->fd);
+ close(data->fd);
+ }
free(data);
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
return 0;
}
+#ifndef PRIORITY_CONTROLLER_INTERNAL
int priority_controller_callback(interface_t * interface, int fd, void * unused)
{
pc_data_t * data = (pc_data_t*)interface->data;
@@ -148,10 +285,13 @@ int priority_controller_callback(interface_t * interface, int fd, void * unused)
return 0;
}
+#endif /* ! PRIORITY_CONTROLLER_INTERNAL */
interface_ops_t priority_controller_ops = {
.type = "priority_controller",
.initialize = priority_controller_initialize,
.finalize = priority_controller_finalize,
+#ifndef PRIORITY_CONTROLLER_INTERNAL
.callback = priority_controller_callback,
+#endif /* ! PRIORITY_CONTROLLER_INTERNAL */
};
diff --git a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h
new file mode 100644
index 000000000..247fc3c57
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file priority_controller.h
+ * \brief Priority Controller interface
+ */
+
+#ifndef FACEMGR_INTERFACE_PRIORITY_CONTROLLER
+#define FACEMGR_INTERFACE_PRIORITY_CONTROLLER
+
+#define FACEMGR_UTILITY_CLASS "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility"
+
+/*
+ * Uncomment this line to use a Priority controller interface internal to the
+ * face manager (only available in Android).
+ */
+// #define PRIORITY_CONTROLLER_INTERNAL
+
+#ifdef __ANDROID__
+#include <jni.h>
+#endif /* __ANDROID__ */
+
+typedef struct {
+#ifdef __ANDROID__
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+ JavaVM * jvm;
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
+#endif /* __ANDROID__ */
+} priority_controller_cfg_t;
+
+
+#endif /* FACEMGR_INTERFACE_PRIORITY_CONTROLLER */
diff --git a/ctrl/facemgr/src/main.c b/ctrl/facemgr/src/main.c
index da5e55943..344b034ae 100644
--- a/ctrl/facemgr/src/main.c
+++ b/ctrl/facemgr/src/main.c
@@ -186,7 +186,7 @@ MAIN_LOOP:
facemgr_set_callback(facemgr, loop, (void*)loop_callback);
#ifdef __ANDROID__
- facemgr_set_jvm(facemgr, NULL, NULL); // FIXME
+ facemgr_set_jvm(facemgr, NULL);
#endif /* __ ANDROID__ */
DEBUG("Bootstrap...");