• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define TLOG_TAG "metrics-consumer"
18 #include "consumer.h"
19 
20 #include <interface/metrics/consumer.h>
21 #include <lib/tipc/tipc.h>
22 #include <lib/tipc/tipc_srv.h>
23 #include <metrics_consts.h>
24 #include <stddef.h>
25 #include <string.h>
26 #include <trusty_log.h>
27 #include <uapi/err.h>
28 
29 /*
30 Current use cases:
31 1) Metrics daemon
32 2) Trusty kernel metrics reporter
33 3) Storage metrics
34 4) Android metrics test
35 */
36 #define MAX_METRICS_TA_CONNECTIONS 4
37 
38 static const struct uuid zero_uuid = UUID_INITIAL_VALUE(zero_uuid);
39 
is_zero_uuid(const struct uuid * peer)40 static bool is_zero_uuid(const struct uuid* peer) {
41     return equal_uuid(peer, &zero_uuid);
42 }
43 
on_connect(const struct tipc_port * port,handle_t chan,const struct uuid * peer,void ** ctx_p)44 static int on_connect(const struct tipc_port* port,
45                       handle_t chan,
46                       const struct uuid* peer,
47                       void** ctx_p) {
48 
49     struct srv_state* state = get_srv_state(port);
50     if(is_zero_uuid(peer))
51     {
52         TLOGD("Updating metrics daemon handle :%d\n", chan);
53         if(state->ns_handle != INVALID_IPC_HANDLE) {
54                 close(state->ns_handle);
55         }
56         state->ns_handle = chan;
57     }
58 
59     return NO_ERROR;
60 }
61 
on_message(const struct tipc_port * port,handle_t chan,void * ctx)62 static int on_message(const struct tipc_port* port, handle_t chan, void* ctx) {
63     int rc;
64     struct metrics_req req;
65     uint8_t msg[METRICS_MAX_MSG_SIZE];
66 
67     memset(msg, 0, sizeof(msg));
68     int msg_size = tipc_recv1(chan, sizeof(req), msg, sizeof(msg));
69     if (msg_size < 0) {
70         TLOGE("failed (%d) to receive metrics event\n", msg_size);
71         return msg_size;
72     }
73 
74     // Check if NS metricsd connected, if so forward it there.
75     struct srv_state* state = get_srv_state(port);
76     if(is_ns_connected(state)) {
77         rc = tipc_send1(state->ns_handle, msg, msg_size);
78         if (rc < 0) {
79             TLOGE("failed (%d) to send metrics event tp NS metricsd\n", rc);
80             return rc;
81         }
82     }
83     else {
84         TLOGD("NS metrics daemon not connected\n");
85     }
86 
87     uint32_t cmd;
88     cmd = ((struct metrics_req*)msg)->cmd;
89     struct metrics_resp resp = {
90         .cmd = (cmd | METRICS_CMD_RESP_BIT)
91     };
92 
93     rc = tipc_send1(chan, &resp, sizeof(resp));
94     if (rc < 0) {
95         TLOGE("failed (%d) to send metrics event response\n", rc);
96         return rc;
97     }
98 
99     if ((size_t)rc != sizeof(resp)) {
100         TLOGE("unexpected number of bytes sent: %d\n", rc);
101         return ERR_BAD_LEN;
102     }
103 
104     return NO_ERROR;
105 }
106 
add_metrics_consumer_service(struct tipc_hset * hset,struct srv_state * state)107 int add_metrics_consumer_service(struct tipc_hset* hset, struct srv_state* state) {
108     static struct tipc_port_acl port_acl = {
109             .flags = IPC_PORT_ALLOW_TA_CONNECT | IPC_PORT_ALLOW_NS_CONNECT,
110     };
111     static struct tipc_port port = {
112             .name = METRICS_CONSUMER_PORT,
113             .msg_max_size = METRICS_MAX_MSG_SIZE,
114             .msg_queue_len = 1,
115             .acl = &port_acl,
116     };
117     static struct tipc_srv_ops ops = {
118             .on_message = on_message,
119             .on_connect = on_connect,
120     };
121     set_srv_state(&port, state);
122 
123     return tipc_add_service(hset, &port, 1, MAX_METRICS_TA_CONNECTIONS, &ops);
124 }