Front Haul Interface Library first seed code contribution
[o-du/phy.git] / fhi_lib / lib / src / xran_sync_api.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 Intel.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 *
17 *******************************************************************************/
18
19 /**
20  * @brief This file provides implementation of synchronization related APIs (PTP/1588)
21  *        for XRAN.
22  *
23  * @file xran_sync_api.c
24  * @ingroup group_lte_source_xran
25  * @author Intel Corporation
26  *
27  **/
28
29 #include <assert.h>
30 #include <dirent.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <dirent.h>
38 #include <math.h>
39
40 #include "xran_sync_api.h"
41 #include "xran_printf.h"
42
43 #define BUF_LEN 256
44 #define PROC_DIR "/proc"
45 #define COMM_FILE "comm"
46 #define PMC_CMD "pmc -u -b 0 'GET PORT_DATA_SET'"
47 #define PTP4L_PROC_NAME "ptp4l"
48 #define PHC2SYS_PROC_NAME "phc2sys"
49
50 static int find_substr(const char *str, const unsigned int str_len,
51     const char *substr, const unsigned int substr_len)
52 {
53     assert(str);
54     assert(substr);
55     unsigned int ind = 0;
56
57     while (ind + substr_len <= str_len) {
58         if (0 == strncmp(&str[ind], substr, substr_len))
59             return 0;
60         ++ind;
61     }
62     return 1;
63 }
64
65 static int is_process_running(char *pname)
66 {
67     char full_path[BUF_LEN] = {0};
68     char read_proc_name[BUF_LEN] = {0};
69     int res = 1;
70     int null = 0;
71     int dir_fd = dirfd((DIR*)PROC_DIR);
72     DIR *dir = fdopendir(dir_fd);
73     if (NULL == dir) {
74         return 1;
75     }
76
77     struct dirent *entry = NULL;
78     while ((entry = readdir(dir))) {
79         long pid = atol(entry->d_name);
80         if (0 == pid)
81             continue;
82
83         snprintf(full_path, BUF_LEN,"%s/%ld/%s", PROC_DIR, pid, COMM_FILE);
84         int proc_name_file = open(full_path, O_RDONLY);
85         if (null == proc_name_file)
86             continue;
87         fgets( read_proc_name, BUF_LEN, (FILE*)proc_name_file);
88         if (0 == strncmp(read_proc_name, pname, strlen(pname))) {
89             res = 0;
90             close(proc_name_file);
91             break;
92         }
93         close(proc_name_file);
94     }
95     closedir(dir);
96     return res;
97 }
98
99 static int check_ptp_status()
100 {
101     char pmc_out_line[BUF_LEN];
102     const char *keywords[2] = {"portState", "SLAVE"};
103     int res = 1;
104     FILE *pmc_pipe = popen(PMC_CMD, "r");
105     if (NULL == pmc_pipe)
106         return 1;
107
108     while(fgets(pmc_out_line, BUF_LEN, pmc_pipe)) {
109         if (0 == find_substr(pmc_out_line, strlen(pmc_out_line), keywords[0],
110             strlen(keywords[0]))) {
111             if (0 == find_substr(pmc_out_line, strlen(pmc_out_line),
112                 keywords[1], strlen(keywords[1]))) {
113                 res = 0;
114                 break;
115             }
116         }
117     }
118     fclose(pmc_pipe);
119     return res;
120 }
121
122 int xran_is_synchronized()
123 {
124     int res = 0;
125     res |= is_process_running(PTP4L_PROC_NAME);
126     print_dbg("PTP4L_PROC_NAME %d\n", res);
127     res |= is_process_running(PHC2SYS_PROC_NAME);
128     print_dbg("PHC2SYS_PROC_NAME %d\n", res);
129     res |= check_ptp_status();
130     print_dbg("check_ptp_status %d\n", res);
131     return res;
132 }