diff options
author | Jordan Augé <jordan.auge+fdio@cisco.com> | 2019-11-17 00:07:12 +0100 |
---|---|---|
committer | Jordan Augé <jordan.auge+fdio@cisco.com> | 2019-11-17 11:03:31 +0100 |
commit | 2ada8954ecd3601d115a22696c4c3ab90858cec3 (patch) | |
tree | 6db983388333e8776eecaf9c07c5b7bd6f2f10be | |
parent | 2dcc25795fab0100ce33852f08d77a5fd90d8f14 (diff) |
[HICN-379] Add face priority support in face manager
Change-Id: If4f75d44fc66414a4a70135de7827f5082b97112
Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com>
21 files changed, 414 insertions, 14 deletions
diff --git a/ctrl/facemgr/includes/hicn/facemgr/facelet.h b/ctrl/facemgr/includes/hicn/facemgr/facelet.h index db76ccdb9..a0318b206 100644 --- a/ctrl/facemgr/includes/hicn/facemgr/facelet.h +++ b/ctrl/facemgr/includes/hicn/facemgr/facelet.h @@ -161,6 +161,7 @@ extern const char * facelet_attr_status_str_short[]; /* Facelet attribute */ +#ifdef WITH_POLICY #define foreach_facelet_attr \ _(netdevice_type_t, netdevice_type) \ _(netdevice_t, netdevice) \ @@ -171,7 +172,21 @@ extern const char * facelet_attr_status_str_short[]; _(u16, remote_port) \ _(face_state_t, admin_state) \ _(face_state_t, state) \ + _(u32, priority) \ _(facemgr_face_type_t, face_type) +#else +#define foreach_facelet_attr \ + _(netdevice_type_t, netdevice_type) \ + _(netdevice_t, netdevice) \ + _(int, family) \ + _(ip_address_t, local_addr) \ + _(u16, local_port) \ + _(ip_address_t, remote_addr) \ + _(u16, remote_port) \ + _(face_state_t, admin_state) \ + _(face_state_t, state) \ + _(facemgr_face_type_t, face_type) +#endif /* WITH_POLICY */ #define foreach_facelet_event \ _(UNDEFINED) \ diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c index 761f920c4..929005f57 100644 --- a/ctrl/facemgr/src/facelet.c +++ b/ctrl/facemgr/src/facelet.c @@ -124,6 +124,9 @@ facelet_create() facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET; facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET; facelet->state_status = FACELET_ATTR_STATUS_UNSET; +#ifdef WITH_POLICY + facelet->priority_status = FACELET_ATTR_STATUS_UNSET; +#endif /* WITH_POLICY */ facelet->face_type_status = FACELET_ATTR_STATUS_UNSET; facelet->status = FACELET_STATUS_UNDEFINED; @@ -312,6 +315,16 @@ facelet_create_from_face(face_t * face) facelet->state_status = FACELET_ATTR_STATUS_UNSET; } +#ifdef WITH_POLICY + /* Attribute : priority */ + if (face->priority > 0) { + facelet->priority = face->priority; + facelet->priority_status = FACELET_ATTR_STATUS_CLEAN; + } else { + facelet->priority_status = FACELET_ATTR_STATUS_UNSET; + } +#endif /* WITH_POLICY */ + /* Attribute : face_type */ if ((face->type != FACE_TYPE_UNDEFINED) && (face->type != FACE_TYPE_N)) { switch(face->type) { @@ -809,6 +822,15 @@ facelet_get_face(const facelet_t * facelet, face_t ** pface) face->state = FACE_STATE_UP; } +#ifdef WITH_POLICY + /* Priority */ + if (facelet_has_priority(facelet)) { + if (facelet_get_priority(facelet, &face->priority) < 0) + goto ERR; + } else { + face->priority = 0; + } + /* Tags */ /* - based on netdevice type */ @@ -839,6 +861,7 @@ facelet_get_face(const facelet_t * facelet, face_t ** pface) } } face->tags = tags; +#endif /* WITH_POLICY */ *pface = face; @@ -1105,6 +1128,18 @@ facelet_snprintf(char * s, size_t size, const facelet_t * facelet) return cur - s; } +#ifdef WITH_POLICY + /* Priority */ + if (facelet_has_priority(facelet)) { + rc = snprintf(cur, s + size - cur, " priority=%d", facelet->priority); + if (rc < 0) + return rc; + cur += rc; + if (cur >= s + size) + return cur - s; + } +#endif /* WITH_POLICY */ + /* Face type */ if (facelet_has_face_type(facelet)) { rc = snprintf(cur, s + size - cur, " face_type=LAYER%s/%s", @@ -1327,6 +1362,19 @@ int facelet_snprintf_json(char * s, size_t size, const facelet_t * facelet, int return cur - s; } +#ifdef WITH_POLICY + /* Priority */ + if (facelet_has_priority(facelet)) { + rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "", + "\"priority\"", facelet->priority); + if (rc < 0) + return rc; + cur += rc; + if (cur >= s + size) + return cur - s; + } +#endif /* WITH_POLICY */ + if (facelet_has_face_type(facelet)) { rc = snprintf(cur, s + size - cur, "%*s%s: \"LAYER%s/%s\",\n", 4 * (indent+1), "", "\"face_type\"", diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c index 53aa95a75..a6cd44fe0 100644 --- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c +++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c @@ -294,9 +294,12 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet) int rc; int ret = 0; hl_data_t * data = (hl_data_t *)interface->data; - face_t * face = NULL; + hc_face.id = 0; + memset(hc_face.name, 0, sizeof(hc_face.name)); + + /* NOTE * - One example where this fails (and it is normal) is when we delete a * face that was not completely created, because for instance bonjour did @@ -324,8 +327,6 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet) facelet_snprintf(buf, MAXSZ_FACELET, facelet); DEBUG("Create facelet %s", buf); } - hc_face.id = 0; - memset(hc_face.name, 0, sizeof(hc_face.name)); hc_face.face = *face; rc = hc_face_create(data->s, &hc_face); if (rc < 0) { @@ -415,7 +416,7 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet) break; case FACELET_EVENT_UPDATE: - /* Currently, only admin_state is supported */ + /* Currently, only admin_state & priority are supported */ if (facelet_get_admin_state_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { hc_face.face = *face; hc_face_t * face_found; @@ -449,6 +450,35 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet) } INFO("Admin state updated"); } + if (facelet_get_admin_state_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { + hc_face.face = *face; + hc_face_t * face_found; + + rc = hc_face_get(data->s, &hc_face, &face_found); + if (rc < 0) { + ERROR("Failed to find face\n"); + goto ERR; + } + if (!face_found) { + ERROR("Face to update has not been found"); + goto ERR; + } + char conn_id_or_name[SYMBOLIC_NAME_LEN]; + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); + free(face_found); + + uint32_t priority; + if (facelet_get_priority(facelet, &priority) < 0) { + ERROR("Failed to retrieve facelet priority"); + goto ERR; + } + + if (hc_connection_set_priority(data->s, conn_id_or_name, priority) < 0) { + ERROR("Failed to update priority"); + goto ERR; + } + INFO("Priority updated"); + } break; default: diff --git a/ctrl/libhicnctrl/examples/create_face.c b/ctrl/libhicnctrl/examples/create_face.c index dcacaeff1..5f92f5906 100644 --- a/ctrl/libhicnctrl/examples/create_face.c +++ b/ctrl/libhicnctrl/examples/create_face.c @@ -107,7 +107,10 @@ int main() { .remote_port = 6000, .admin_state = FACE_STATE_UNDEFINED, .state = FACE_STATE_UNDEFINED, +#ifdef WITH_POLICY + .priority = 0, .tags = POLICY_TAGS_EMPTY, +#endif /* WITH_POLICY */ }, }; if (netdevice_set_name(&face.face.netdevice, if_name) < 0) { diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h index d6bb282cb..c9c2f0da8 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h @@ -498,6 +498,7 @@ typedef struct { u16 remote_port; /* .rw */ hc_connection_state_t admin_state; /* .rw */ #ifdef WITH_POLICY + uint32_t priority; /* .rw */ policy_tags_t tags; /* .rw */ #endif /* WITH_POLICY */ hc_connection_state_t state; /* .r. */ @@ -523,8 +524,9 @@ int hc_connection_validate(const hc_connection_t * connection); int hc_connection_cmp(const hc_connection_t * c1, const hc_connection_t * c2); int hc_connection_parse(void * in, hc_connection_t * connection); -#ifdef WITH_POLICY int hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t state); +#ifdef WITH_POLICY +int hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, uint32_t priority); #endif /* WITH_POLICY */ #define foreach_connection(VAR, data) foreach_type(hc_connection_t, VAR, data) diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h index a5bc15e8a..520559ccf 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h @@ -75,6 +75,7 @@ typedef enum { LIST_POLICIES, REMOVE_POLICY, UPDATE_CONNECTION, + CONNECTION_SET_PRIORITY, #endif /* WITH_POLICY */ LAST_COMMAND_VALUE } command_id; @@ -138,6 +139,7 @@ typedef struct { uint8_t connectionType; uint8_t admin_state; #ifdef WITH_POLICY + uint32_t priority; policy_tags_t tags; #endif /* WITH_POLICY */ } add_connection_command; @@ -166,6 +168,9 @@ typedef struct { uint32_t connid; uint8_t state; uint8_t admin_state; +#ifdef WITH_POLICY + uint32_t priority; +#endif /* WITH_POLICY */ char interfaceName[SYMBOLIC_NAME_LEN]; char connectionName[SYMBOLIC_NAME_LEN]; } list_connections_command; @@ -335,9 +340,15 @@ typedef struct { typedef struct { char symbolicOrConnid[SYMBOLIC_NAME_LEN]; uint8_t admin_state; + uint32_t priority; policy_tags_t tags; } update_connection_command; +typedef struct { + char symbolicOrConnid[SYMBOLIC_NAME_LEN]; + uint32_t priority; +} connection_set_priority_command; + #endif /* WITH_POLICY */ //===== size of commands ====== @@ -394,6 +405,8 @@ static inline int payloadLengthDaemon(command_id id) { return sizeof(remove_policy_command); case UPDATE_CONNECTION: return sizeof(update_connection_command); + case CONNECTION_SET_PRIORITY: + return sizeof(connection_set_priority_command); #endif /* WITH_POLICY */ case LAST_COMMAND_VALUE: return 0; diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h index 5c1fecd55..f0a8045de 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/face.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/face.h @@ -153,6 +153,7 @@ typedef struct { face_state_t admin_state; face_state_t state; #ifdef WITH_POLICY + uint32_t priority; policy_tags_t tags; /**< \see policy_tag_t */ #endif /* WITH_POLICY */ diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c index 74a8821e2..14ee69b53 100644 --- a/ctrl/libhicnctrl/src/api.c +++ b/ctrl/libhicnctrl/src/api.c @@ -1269,6 +1269,7 @@ _hc_connection_create(hc_sock_t * s, hc_connection_t * connection, bool async) .connectionType = (u8)map_to_connection_type[connection->type], .admin_state = connection->admin_state, #ifdef WITH_POLICY + .priority = connection->priority, .tags = connection->tags, #endif /* WITH_POLICY */ } @@ -1546,6 +1547,7 @@ hc_connection_parse(void * in, hc_connection_t * connection) .remote_port = ntohs(cmd->connectionData.remotePort), .admin_state = cmd->connectionData.admin_state, #ifdef WITH_POLICY + .priority = cmd->connectionData.priority, .tags = cmd->connectionData.tags, #endif /* WITH_POLICY */ .state = state, @@ -1646,6 +1648,56 @@ hc_connection_set_admin_state_async(hc_sock_t * s, const char * conn_id_or_name, return _hc_connection_set_admin_state(s, conn_id_or_name, state, true); } +int +_hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, + uint32_t priority, bool async) +{ + int rc; + DEBUG("[hc_connection_set_priority] connection_id/name=%s priority=%d async=%s", + conn_id_or_name, priority, BOOLSTR(async)); + struct { + header_control_message hdr; + connection_set_priority_command payload; + } msg = { + .hdr = { + .messageType = REQUEST_LIGHT, + .commandID = CONNECTION_SET_ADMIN_STATE, + .length = 1, + .seqNum = 0, + }, + .payload = { + .priority = priority, + }, + }; + rc = snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name); + if (rc >= SYMBOLIC_NAME_LEN) + WARN("[_hc_connection_set_priority] Unexpected truncation of symbolic name string"); + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = CONNECTION_SET_PRIORITY, + .size_in = sizeof(connection_set_priority_command), + .size_out = 0, + .parse = NULL, + }; + + return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), ¶ms, NULL, async); +} + +int +hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name, + uint32_t priority) +{ + return _hc_connection_set_priority(s, conn_id_or_name, priority, false); +} + +int +hc_connection_set_priority_async(hc_sock_t * s, const char * conn_id_or_name, + uint32_t priority) +{ + return _hc_connection_set_priority(s, conn_id_or_name, priority, true); +} + /*----------------------------------------------------------------------------* * Routes *----------------------------------------------------------------------------*/ @@ -1924,6 +1976,7 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool .admin_state = face_state_to_connection_state(f->admin_state), .state = face_state_to_connection_state(f->state), #ifdef WITH_POLICY + .priority = f->priority, .tags = f->tags, #endif /* WITH_POLICY */ }; @@ -1943,6 +1996,7 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool .admin_state = face_state_to_connection_state(f->admin_state), .state = face_state_to_connection_state(f->state), #ifdef WITH_POLICY + .priority = f->priority, .tags = f->tags, #endif /* WITH_POLICY */ }; @@ -1965,6 +2019,7 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool .admin_state = face_state_to_connection_state(f->admin_state), .state = face_state_to_connection_state(f->state), #ifdef WITH_POLICY + .priority = f->priority, .tags = f->tags, #endif /* WITH_POLICY */ }; @@ -2010,6 +2065,7 @@ hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face) .admin_state = connection_state_to_face_state(connection->admin_state), .state = connection_state_to_face_state(connection->state), #ifdef WITH_POLICY + .priority = connection->priority, .tags = connection->tags, #endif /* WITH_POLICY */ }, @@ -2028,6 +2084,7 @@ hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face) .admin_state = connection_state_to_face_state(connection->admin_state), .state = connection_state_to_face_state(connection->state), #ifdef WITH_POLICY + .priority = connection->priority, .tags = connection->tags, #endif /* WITH_POLICY */ }, @@ -2045,6 +2102,7 @@ hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face) .admin_state = connection_state_to_face_state(connection->admin_state), .state = connection_state_to_face_state(connection->state), #ifdef WITH_POLICY + .priority = connection->priority, .tags = connection->tags, #endif /* WITH_POLICY */ }, @@ -2450,7 +2508,7 @@ hc_face_snprintf(char * s, size_t size, hc_face_t * face) if (rc < 0) return rc; - return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s (%s)", + return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s [%d] (%s)", face->id, face->name, face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->face.netdevice.name : "*", @@ -2459,6 +2517,7 @@ hc_face_snprintf(char * s, size_t size, hc_face_t * face) remote, face_state_str[face->face.state], face_state_str[face->face.admin_state], + face->face.priority, tags); #else return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s", @@ -2474,12 +2533,19 @@ hc_face_snprintf(char * s, size_t size, hc_face_t * face) } int -hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, // XXX wrong identifier +hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, face_state_t admin_state) { return hc_connection_set_admin_state(s, conn_id_or_name, admin_state); } +int +hc_face_set_priority(hc_sock_t * s, const char * conn_id_or_name, + uint32_t priority) +{ + return hc_connection_set_priority(s, conn_id_or_name, priority); +} + /*----------------------------------------------------------------------------* * Punting *----------------------------------------------------------------------------*/ diff --git a/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c b/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c index ab0e0e6d8..1f5d33e24 100644 --- a/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c +++ b/hicn-light/src/hicn/command_line/controller/hicnLightControl_main.c @@ -82,6 +82,7 @@ static int payloadLengthController[LAST_COMMAND_VALUE] = { sizeof(list_policies_command), sizeof(remove_policy_command), sizeof(update_connection_command), + sizeof(connection_set_priority_command), #endif }; diff --git a/hicn-light/src/hicn/config/configuration.c b/hicn-light/src/hicn/config/configuration.c index 01192569f..f135dcc5a 100644 --- a/hicn-light/src/hicn/config/configuration.c +++ b/hicn-light/src/hicn/config/configuration.c @@ -420,6 +420,7 @@ struct iovec *configuration_ProcessCreateTunnel(Configuration *config, Connection *conn = connection_Create(ops); #ifdef WITH_POLICY connection_SetTags(conn, control->tags); + connection_SetPriority(conn, control->priority); #endif /* WITH_POLICY */ connection_SetAdminState(conn, control->admin_state); @@ -443,6 +444,7 @@ struct iovec *configuration_ProcessCreateTunnel(Configuration *config, } else { #ifdef WITH_POLICY connection_SetTags(conn, control->tags); + connection_SetPriority(conn, control->priority); connection_SetAdminState(conn, control->admin_state); #ifdef WITH_MAPME @@ -704,6 +706,7 @@ struct iovec *configuration_ProcessConnectionList(Configuration *config, listConnectionsCommand->connectionData.admin_state = connection_GetAdminState(original); #ifdef WITH_POLICY + listConnectionsCommand->priority = connection_GetPriority(original); listConnectionsCommand->connectionData.tags = connection_GetTags(original); #endif /* WITH_POLICY */ @@ -1162,7 +1165,7 @@ struct iovec *configuration_ConnectionSetAdminState(Configuration *config, connection_SetAdminState(conn, control->admin_state); #ifdef WITH_MAPME - /* Hook: new connection created through the control protocol */ + /* Hook: connection event */ forwarder_onConnectionEvent(config->forwarder, conn, control->admin_state == CONNECTION_STATE_UP ? CONNECTION_EVENT_SET_UP @@ -1173,6 +1176,27 @@ struct iovec *configuration_ConnectionSetAdminState(Configuration *config, } #ifdef WITH_POLICY + +struct iovec *configuration_ConnectionSetPriority(Configuration *config, + struct iovec *request) { + header_control_message *header = request[0].iov_base; + connection_set_priority_command *control = request[1].iov_base; + + Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid); + if (!conn) + return utils_CreateNack(header, control, sizeof(connection_set_priority_command)); + + connection_SetPriority(conn, control->priority); + +#ifdef WITH_MAPME + /* Hook: connection event */ + forwarder_onConnectionEvent(config->forwarder, conn, + CONNECTION_EVENT_PRIORITY_CHANGED); +#endif /* WITH_MAPME */ + + return utils_CreateAck(header, control, sizeof(connection_set_priority_command)); +} + struct iovec *configuration_ProcessPolicyAdd(Configuration *config, struct iovec *request) { header_control_message *header = request[0].iov_base; @@ -1256,12 +1280,14 @@ struct iovec *configuration_UpdateConnection(Configuration *config, Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid); if (!conn) - return utils_CreateNack(header, control, sizeof(connection_set_admin_state_command)); + return utils_CreateNack(header, control, sizeof(update_connection_command)); connection_SetTags(conn, control->tags); connection_SetAdminState(conn, control->admin_state); + if (control->priority > 0) + connection_SetPriority(conn, control->priority); - return utils_CreateAck(header, control, sizeof(remove_policy_command)); + return utils_CreateAck(header, control, sizeof(update_connection_command)); } #endif /* WITH_POLICY */ @@ -1372,6 +1398,10 @@ struct iovec *configuration_DispatchCommand(Configuration *config, case UPDATE_CONNECTION: response = configuration_UpdateConnection(config, control); break; + + case CONNECTION_SET_PRIORITY: + response = configuration_ConnectionSetPriority(config, control); + break; #endif /* WITH_POLICY */ default: diff --git a/hicn-light/src/hicn/config/controlListConnections.c b/hicn-light/src/hicn/config/controlListConnections.c index 0e8e2c30b..0613ac4f9 100644 --- a/hicn-light/src/hicn/config/controlListConnections.c +++ b/hicn-light/src/hicn/config/controlListConnections.c @@ -114,7 +114,7 @@ static CommandReturn _controlListConnections_Execute(CommandParser *parser, } #ifdef WITH_POLICY - printf("%5s %10s %12s %6s %40s %40s %5s %s\n", "id", "name", "admin_state", "state", "source", "destination", "type", "flags"); + printf("%5s %10s %12s %6s %40s %40s %5s %s %s\n", "id", "name", "admin_state", "state", "source", "destination", "type", "priority", "flags"); #else printf("%5s %10s %12s %6s %40s %40s %5s\n", "id", "name", "admin_state", "state", "source", "destination", "type"); #endif /* WITH_POLICY */ @@ -147,11 +147,12 @@ foreach_policy_tag *s = '\0'; parcBufferComposer_Format( - composer, "%5d %10s %12s %6s %40s %40s %5s [%s]", listConnectionsCommand->connid, listConnectionsCommand->connectionName, + composer, "%5d %10s %12s %6s %40s %40s %5s [%d] [%s]", listConnectionsCommand->connid, listConnectionsCommand->connectionName, stateString[listConnectionsCommand->admin_state], stateString[listConnectionsCommand->state], sourceString, destinationString, connTypeString[listConnectionsCommand->connectionData.connectionType], + listConnectionsCommand->connectionData.priority, flags_str); #else diff --git a/hicn-light/src/hicn/core/connection.c b/hicn-light/src/hicn/core/connection.c index 6295d08df..8ec38f75f 100644 --- a/hicn-light/src/hicn/core/connection.c +++ b/hicn-light/src/hicn/core/connection.c @@ -332,6 +332,26 @@ void connection_SetAdminState(Connection *conn, connection_state_t admin_state) ioOperations_SetAdminState(conn->ops, admin_state); } +#ifdef WITH_POLICY +uint32_t connection_GetPriority(const Connection *conn) +{ + parcAssertNotNull(conn, "Parameter conn must be non-null"); + if (!conn->ops) + return CONNECTION_STATE_UNDEFINED; + return ioOperations_GetPriority(conn->ops); +} + +void connection_SetPriority(Connection *conn, uint32_t priority) +{ + parcAssertNotNull(conn, "Parameter conn must be non-null"); + if (!conn->ops) + return; + if ((priority != CONNECTION_STATE_UP) && (priority != CONNECTION_STATE_DOWN)) + return; + ioOperations_SetPriority(conn->ops, priority); +} +#endif /* WITH_POLICY */ + const char * connection_GetInterfaceName(const Connection * conn) { parcAssertNotNull(conn, "Parameter conn must be non-null"); diff --git a/hicn-light/src/hicn/core/connection.h b/hicn-light/src/hicn/core/connection.h index b7b5e3c91..3b647dd7a 100644 --- a/hicn-light/src/hicn/core/connection.h +++ b/hicn-light/src/hicn/core/connection.h @@ -36,6 +36,7 @@ typedef enum { CONNECTION_EVENT_UPDATE, CONNECTION_EVENT_SET_UP, CONNECTION_EVENT_SET_DOWN, + CONNECTION_EVENT_PRIORITY_CHANGED, } connection_event_t; #endif /* WITH_MAPME */ @@ -183,6 +184,12 @@ connection_state_t connection_GetAdminState(const Connection *conn); void connection_SetAdminState(Connection *conn, connection_state_t admin_state); +#ifdef WITH_POLICY +uint32_t connection_GetPriority(const Connection *conn); + +void connection_SetPriority(Connection *conn, uint32_t priority); +#endif /* WITH_POLICY */ + const char * connection_GetInterfaceName(const Connection * conn); #ifdef WITH_POLICY diff --git a/hicn-light/src/hicn/core/mapme.c b/hicn-light/src/hicn/core/mapme.c index 94ada3afa..0eba02e49 100644 --- a/hicn-light/src/hicn/core/mapme.c +++ b/hicn-light/src/hicn/core/mapme.c @@ -488,6 +488,7 @@ void mapme_onConnectionEvent(const MapMe *mapme, const Connection *conn_added, c case CONNECTION_EVENT_DELETE: case CONNECTION_EVENT_SET_DOWN: case CONNECTION_EVENT_UPDATE: + case CONNECTION_EVENT_PRIORITY_CHANGED: break; } } diff --git a/hicn-light/src/hicn/io/hicnConnection.c b/hicn-light/src/hicn/io/hicnConnection.c index d56231c38..e35454438 100644 --- a/hicn-light/src/hicn/io/hicnConnection.c +++ b/hicn-light/src/hicn/io/hicnConnection.c @@ -78,6 +78,9 @@ typedef struct hicn_state { * but it is currently not reachable from within the implementation. */ connection_state_t state; connection_state_t admin_state; +#ifdef WITH_POLICY + uint32_t priority; +#endif /* WITH_POLICY */ } _HicnState; // Prototypes @@ -97,6 +100,10 @@ static connection_state_t _getState(const IoOperations *ops); static void _setState(IoOperations *ops, connection_state_t state); static connection_state_t _getAdminState(const IoOperations *ops); static void _setAdminState(IoOperations *ops, connection_state_t admin_state); +#ifdef WITH_POLICY +static uint32_t _getPriority(const IoOperations *ops); +static void _setPriority(IoOperations *ops, uint32_t priority); +#endif /* WITH_POLICY */ static const char * _getInterfaceName(const IoOperations *ops); /* @@ -129,6 +136,10 @@ static IoOperations _template = { .setState = &_setState, .getAdminState = &_getAdminState, .setAdminState = &_setAdminState, +#ifdef WITH_POLICY + .getPriority = &_getPriority, + .setPriority = &_setPriority, +#endif /* WITH_POLICY */ .getInterfaceName = &_getInterfaceName, }; @@ -168,6 +179,10 @@ IoOperations *hicnConnection_Create(Forwarder *forwarder, const char * interface _setConnectionState(hicnConnState, true); +#ifdef WITH_POLICY + hicnConnState->priority = 0; +#endif /* WITH_POLICY */ + if (logger_IsLoggable(hicnConnState->logger, LoggerFacility_IO, PARCLogLevel_Info)) { char *str = addressPair_ToString(hicnConnState->addressPair); @@ -592,6 +607,22 @@ static void _setAdminState(IoOperations *ops, connection_state_t admin_state) { hicnConnState->admin_state = admin_state; } +#ifdef WITH_POLICY +static uint32_t _getPriority(const IoOperations *ops) { + parcAssertNotNull(ops, "Parameter must be non-null"); + const _HicnState *hicnConnState = + (const _HicnState *)ioOperations_GetClosure(ops); + return hicnConnState->priority; +} + +static void _setPriority(IoOperations *ops, uint32_t priority) { + parcAssertNotNull(ops, "Parameter must be non-null"); + _HicnState *hicnConnState = + (_HicnState *)ioOperations_GetClosure(ops); + hicnConnState->priority = priority; +} +#endif /* WITH_POLICY +*/ static const char * _getInterfaceName(const IoOperations *ops) { parcAssertNotNull(ops, "Parameter must be non-null"); diff --git a/hicn-light/src/hicn/io/ioOperations.c b/hicn-light/src/hicn/io/ioOperations.c index b2d346ed8..336e9f12e 100644 --- a/hicn-light/src/hicn/io/ioOperations.c +++ b/hicn-light/src/hicn/io/ioOperations.c @@ -86,6 +86,16 @@ void ioOperations_SetAdminState(IoOperations *ops, connection_state_t admin_stat ops->setAdminState(ops, admin_state); } +#ifdef WITH_POLICY +uint32_t ioOperations_GetPriority(const IoOperations *ops) { + return ops->getPriority(ops); +} + +void ioOperations_SetPriority(IoOperations *ops, uint32_t priority) { + ops->setPriority(ops, priority); +} +#endif /* WITH_POLICY */ + const char * ioOperations_GetInterfaceName(const IoOperations *ops) { return ops->getInterfaceName(ops); } diff --git a/hicn-light/src/hicn/io/ioOperations.h b/hicn-light/src/hicn/io/ioOperations.h index c8a107199..ee8720e77 100644 --- a/hicn-light/src/hicn/io/ioOperations.h +++ b/hicn-light/src/hicn/io/ioOperations.h @@ -89,6 +89,10 @@ struct io_ops { void (*setState)(IoOperations *ops, connection_state_t state); connection_state_t (*getAdminState)(const IoOperations *ops); void (*setAdminState)(IoOperations *ops, connection_state_t admin_state); +#ifdef WITH_POLICY + uint32_t (*getPriority)(const IoOperations *ops); + void (*setPriority)(IoOperations *ops, uint32_t priority); +#endif /* WITH_POLICY */ const char * (*getInterfaceName)(const IoOperations *ops); }; @@ -416,6 +420,25 @@ connection_state_t ioOperations_GetAdminState(const IoOperations *ops); */ void ioOperations_SetAdminState(IoOperations *ops, connection_state_t admin_state); +#ifdef WITH_POLICY +/** + * Returns the priority of the connection + * + * @param [in] ops The connection implementation. + * + * @return Connection state (uint32_t). + */ +uint32_t ioOperations_GetPriority(const IoOperations *ops); + +/** + * Sets the priority of the connection + * + * @param [in] ops The connection implementation. + * @param [in] state New state to set (uint32_t). + */ +void ioOperations_SetPriority(IoOperations *ops, uint32_t priority); +#endif /* WITH_POLICY */ + /** * Sets the interface name associated to the connection. * diff --git a/hicn-light/src/hicn/io/streamConnection.c b/hicn-light/src/hicn/io/streamConnection.c index 4e2f9c37e..27ec45d48 100644 --- a/hicn-light/src/hicn/io/streamConnection.c +++ b/hicn-light/src/hicn/io/streamConnection.c @@ -66,6 +66,9 @@ typedef struct stream_state { * but it is currently not reachable from within the implementation. */ connection_state_t state; connection_state_t admin_state; +#ifdef WITH_POLICY + uint32_t priority; +#endif /* WITH_POLICY */ } _StreamState; // Prototypes @@ -91,6 +94,10 @@ static connection_state_t _streamConnection_getState(const IoOperations *ops); static void _streamConnection_setState(IoOperations *ops, connection_state_t state); static connection_state_t _streamConnection_getAdminState(const IoOperations *ops); static void _streamConnection_setAdminState(IoOperations *ops, connection_state_t admin_state); +#ifdef WITH_POLICY +static uint32_t _streamConnection_getPriority(const IoOperations *ops); +static void _streamConnection_setPriority(IoOperations *ops, uint32_t priority); +#endif /* WITH_POLICY */ static const char * _streamConnection_getInterfaceName(const IoOperations *ops); /* @@ -123,6 +130,10 @@ static IoOperations _template = { .setState = &_streamConnection_setState, .getAdminState = &_streamConnection_getAdminState, .setAdminState = &_streamConnection_setAdminState, +#ifdef WITH_POLICY + .getPriority = &_streamConnection_getPriority, + .setPriority = &_streamConnection_setPriority, +#endif /* WITH_POLICY */ .getInterfaceName = &_streamConnection_getInterfaceName, }; @@ -147,6 +158,10 @@ IoOperations *streamConnection_AcceptConnection(Forwarder *forwarder, int fd, stream->addressPair = pair; stream->isClosed = false; +#ifdef WITH_POLICY + stream->priority = 0; +#endif /* WITH_POLICY */ + // allocate a connection IoOperations *io_ops = parcMemory_AllocateAndClear(sizeof(IoOperations)); parcAssertNotNull(io_ops, "parcMemory_AllocateAndClear(%zu) returned NULL", @@ -736,6 +751,22 @@ static void _streamConnection_setAdminState(IoOperations *ops, connection_state_ stream->admin_state = admin_state; } +#ifdef WITH_POLICY +static uint32_t _streamConnection_getPriority(const IoOperations *ops) { + parcAssertNotNull(ops, "Parameter must be non-null"); + const _StreamState *stream = + (const _StreamState *)ioOperations_GetClosure(ops); + return stream->priority; +} + +static void _streamConnection_setPriority(IoOperations *ops, uint32_t priority) { + parcAssertNotNull(ops, "Parameter must be non-null"); + _StreamState *stream = + (_StreamState *)ioOperations_GetClosure(ops); + stream->priority = priority; +} +#endif /* WITH_POLICY */ + static const char * _streamConnection_getInterfaceName(const IoOperations *ops) { parcAssertNotNull(ops, "Parameter must be non-null"); diff --git a/hicn-light/src/hicn/io/udpConnection.c b/hicn-light/src/hicn/io/udpConnection.c index 9ad70403f..4e29eba7d 100644 --- a/hicn-light/src/hicn/io/udpConnection.c +++ b/hicn-light/src/hicn/io/udpConnection.c @@ -63,6 +63,9 @@ typedef struct udp_state { * but it is currently not reachable from within the implementation. */ connection_state_t state; connection_state_t admin_state; +#ifdef WITH_POLICY + uint32_t priority; +#endif /* WITH_POLICY */ } _UdpState; // Prototypes @@ -82,6 +85,10 @@ static connection_state_t _getState(const IoOperations *ops); static void _setState(IoOperations *ops, connection_state_t state); static connection_state_t _getAdminState(const IoOperations *ops); static void _setAdminState(IoOperations *ops, connection_state_t admin_state); +#ifdef WITH_POLICY +static uint32_t _getPriority(const IoOperations *ops); +static void _setPriority(IoOperations *ops, uint32_t priority); +#endif /* WITH_POLICY */ static const char * _getInterfaceName(const IoOperations *ops); /* @@ -114,6 +121,10 @@ static IoOperations _template = { .setState = &_setState, .getAdminState = &_getAdminState, .setAdminState = &_setAdminState, +#ifdef WITH_POLICY + .getPriority = &_getPriority, + .setPriority = &_setPriority, +#endif /* WITH_POLICY */ .getInterfaceName = &_getInterfaceName, }; @@ -151,6 +162,10 @@ IoOperations *udpConnection_Create(Forwarder *forwarder, const char * interfaceN _setConnectionState(udpConnState, true); +#ifdef WITH_POLICY + udpConnState->priority = 0; +#endif /* WITH_POLICY */ + if (logger_IsLoggable(udpConnState->logger, LoggerFacility_IO, PARCLogLevel_Info)) { char *str = addressPair_ToString(udpConnState->addressPair); @@ -443,6 +458,22 @@ static void _setAdminState(IoOperations *ops, connection_state_t admin_state) { udpConnState->admin_state = admin_state; } +#ifdef WITH_POLICY +static uint32_t _getPriority(const IoOperations *ops) { + parcAssertNotNull(ops, "Parameter must be non-null"); + const _UdpState *udpConnState = + (const _UdpState *)ioOperations_GetClosure(ops); + return udpConnState->priority; +} + +static void _setPriority(IoOperations *ops, uint32_t priority) { + parcAssertNotNull(ops, "Parameter must be non-null"); + _UdpState *udpConnState = + (_UdpState *)ioOperations_GetClosure(ops); + udpConnState->priority = priority; +} +#endif /* WITH_POLICY */ + static const char * _getInterfaceName(const IoOperations *ops) { parcAssertNotNull(ops, "Parameter must be non-null"); diff --git a/hicn-light/src/hicn/processor/fibEntry.c b/hicn-light/src/hicn/processor/fibEntry.c index 1aaa3ace9..084be7b17 100644 --- a/hicn-light/src/hicn/processor/fibEntry.c +++ b/hicn-light/src/hicn/processor/fibEntry.c @@ -576,16 +576,39 @@ const NumberSet *fibEntry_GetNexthopsFromForwardingStrategy( if (numberSet_Length(available_nexthops) == 0) { out = numberSet_Create(); } else { + + /* Priority */ + NumberSet * priority_nexthops = numberSet_Create(); + + uint32_t max_priority = 0; + for (size_t k = 0; k < numberSet_Length(priority_nexthops); k++) { + unsigned conn_id = numberSet_GetItem(priority_nexthops, k); + const Connection * conn = connectionTable_FindById(table, conn_id); + uint32_t priority = connection_GetPriority(conn); + if (priority < max_priority) { + continue; + } else if (priority == max_priority) { + numberSet_Add(priority_nexthops, conn_id); + } else { /* priority > max_priority */ + numberSet_Release(&priority_nexthops); + priority_nexthops = numberSet_Create(); + numberSet_Add(priority_nexthops, conn_id); + max_priority = priority; + } + } + /* Multipath */ if ((policy.tags[POLICY_TAG_MULTIPATH].state != POLICY_STATE_PROHIBIT) && (policy.tags[POLICY_TAG_MULTIPATH].state != POLICY_STATE_AVOID)) { - out = fibEntry->fwdStrategy->lookupNexthop(fibEntry->fwdStrategy, available_nexthops, + out = fibEntry->fwdStrategy->lookupNexthop(fibEntry->fwdStrategy, priority_nexthops, interestMessage); } else { - unsigned nexthop = numberSet_GetItem(available_nexthops, 0); + unsigned nexthop = numberSet_GetItem(priority_nexthops, 0); out = numberSet_Create(); numberSet_Add(out, nexthop); } + + numberSet_Release(&priority_nexthops); } numberSet_Release(&available_nexthops); diff --git a/hicn-light/src/hicn/utils/commands.h b/hicn-light/src/hicn/utils/commands.h index a5bc15e8a..520559ccf 100644 --- a/hicn-light/src/hicn/utils/commands.h +++ b/hicn-light/src/hicn/utils/commands.h @@ -75,6 +75,7 @@ typedef enum { LIST_POLICIES, REMOVE_POLICY, UPDATE_CONNECTION, + CONNECTION_SET_PRIORITY, #endif /* WITH_POLICY */ LAST_COMMAND_VALUE } command_id; @@ -138,6 +139,7 @@ typedef struct { uint8_t connectionType; uint8_t admin_state; #ifdef WITH_POLICY + uint32_t priority; policy_tags_t tags; #endif /* WITH_POLICY */ } add_connection_command; @@ -166,6 +168,9 @@ typedef struct { uint32_t connid; uint8_t state; uint8_t admin_state; +#ifdef WITH_POLICY + uint32_t priority; +#endif /* WITH_POLICY */ char interfaceName[SYMBOLIC_NAME_LEN]; char connectionName[SYMBOLIC_NAME_LEN]; } list_connections_command; @@ -335,9 +340,15 @@ typedef struct { typedef struct { char symbolicOrConnid[SYMBOLIC_NAME_LEN]; uint8_t admin_state; + uint32_t priority; policy_tags_t tags; } update_connection_command; +typedef struct { + char symbolicOrConnid[SYMBOLIC_NAME_LEN]; + uint32_t priority; +} connection_set_priority_command; + #endif /* WITH_POLICY */ //===== size of commands ====== @@ -394,6 +405,8 @@ static inline int payloadLengthDaemon(command_id id) { return sizeof(remove_policy_command); case UPDATE_CONNECTION: return sizeof(update_connection_command); + case CONNECTION_SET_PRIORITY: + return sizeof(connection_set_priority_command); #endif /* WITH_POLICY */ case LAST_COMMAND_VALUE: return 0; |