blob: 32d7db7eb18d01552d7d29ea424e93e817f525f1 [file] [log] [blame]
Andrew Walbranbc342d42019-02-05 16:56:02 +00001/*
2 * Copyright 2019 The Hafnium Authors.
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 * https://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
Fuad Tabbabfa42bc2019-08-06 13:45:50 +010017#include <errno.h>
Andrew Walbranbc342d42019-02-05 16:56:02 +000018#include <fcntl.h>
Fuad Tabbabfa42bc2019-08-06 13:45:50 +010019#include <stdint.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
Andrew Walbranbc342d42019-02-05 16:56:02 +000023#include <unistd.h>
24
25#include "hf/dlog.h"
Fuad Tabbabfa42bc2019-08-06 13:45:50 +010026#include "hf/socket.h"
Andrew Walbranbc342d42019-02-05 16:56:02 +000027
Andrew Walbran1e7c7742019-12-13 17:10:02 +000028#include "test/hftest.h"
Fuad Tabbabfa42bc2019-08-06 13:45:50 +010029#include <sys/socket.h>
Andrew Walbranbc342d42019-02-05 16:56:02 +000030#include <sys/syscall.h>
Fuad Tabbabfa42bc2019-08-06 13:45:50 +010031#include <sys/types.h>
32
33#define MAX_BUF_SIZE 256
Andrew Walbranbc342d42019-02-05 16:56:02 +000034
35static int finit_module(int fd, const char *param_values, int flags)
36{
Andrew Walbrane52006c2019-10-22 18:01:28 +010037 return (int)syscall(SYS_finit_module, fd, param_values, flags);
Andrew Walbranbc342d42019-02-05 16:56:02 +000038}
39
40static int delete_module(const char *name, int flags)
41{
Andrew Walbrane52006c2019-10-22 18:01:28 +010042 return (int)syscall(SYS_delete_module, name, flags);
Andrew Walbranbc342d42019-02-05 16:56:02 +000043}
44
45static void insmod_hafnium(void)
46{
47 int module_file = open("/hafnium.ko", O_RDONLY);
48 if (module_file < 0) {
49 FAIL("Failed to load Hafnium kernel module from /hafnium.ko");
50 return;
51 }
52 EXPECT_EQ(finit_module(module_file, "", 0), 0);
53 close(module_file);
54}
55
56static void rmmod_hafnium(void)
57{
Andrew Walbranffd11662020-04-20 16:10:23 +010058 int ret = delete_module("hafnium", 0);
59
60 EXPECT_EQ(ret, 0);
61 if (ret != 0) {
62 HFTEST_LOG("Error %d (%s) removing hafnium kernel module.",
63 errno, strerror(errno));
64 }
Andrew Walbranbc342d42019-02-05 16:56:02 +000065}
66
Fuad Tabbabfa42bc2019-08-06 13:45:50 +010067/**
68 * Loads and unloads the Hafnium kernel module.
69 */
Andrew Walbranbc342d42019-02-05 16:56:02 +000070TEST(linux, load_hafnium)
71{
72 insmod_hafnium();
73 rmmod_hafnium();
Andrew Walbranffd11662020-04-20 16:10:23 +010074
75 /* Removing a second time should fail. */
76 EXPECT_EQ(delete_module("hafnium", 0), -1);
77 EXPECT_EQ(errno, ENOENT);
Andrew Walbranbc342d42019-02-05 16:56:02 +000078}
Fuad Tabbabfa42bc2019-08-06 13:45:50 +010079
80/**
81 * Uses the kernel module to send a socket message from the primary VM to a
82 * secondary VM and echoes it back to the primary.
83 */
84TEST(linux, socket_echo_hafnium)
85{
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010086 ffa_vm_id_t vm_id = HF_VM_ID_OFFSET + 1;
Fuad Tabbabfa42bc2019-08-06 13:45:50 +010087 int port = 10;
88 int socket_id;
89 struct hf_sockaddr addr;
90 const char send_buf[] = "The quick brown fox jumps over the lazy dogs.";
Andrew Scull3c351e92020-01-28 11:26:05 +000091 size_t send_len = sizeof(send_buf);
Fuad Tabbabfa42bc2019-08-06 13:45:50 +010092 char resp_buf[MAX_BUF_SIZE];
93 ssize_t recv_len;
94
95 ASSERT_LT(send_len, MAX_BUF_SIZE);
96
97 insmod_hafnium();
98
99 /* Create Hafnium socket. */
100 socket_id = socket(PF_HF, SOCK_DGRAM, 0);
101 if (socket_id == -1) {
102 FAIL("Socket creation failed: %s", strerror(errno));
103 return;
104 }
105 HFTEST_LOG("Socket created successfully.");
106
107 /* Connect to requested VM & port. */
108 addr.family = PF_HF;
109 addr.vm_id = vm_id;
110 addr.port = port;
111 if (connect(socket_id, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
112 FAIL("Socket connection failed: %s", strerror(errno));
113 return;
114 }
115 HFTEST_LOG("Socket to secondary VM %d connected on port %d.", vm_id,
116 port);
117
118 /*
119 * Send a message to the secondary VM.
120 * Enable the confirm flag to try again in case port is busy.
121 */
122 if (send(socket_id, send_buf, send_len, MSG_CONFIRM) < 0) {
123 FAIL("Socket send() failed: %s", strerror(errno));
124 return;
125 }
126 HFTEST_LOG("Packet with length %d sent.", send_len);
127
128 /* Receive a response, which should be an echo of the sent packet. */
129 recv_len = recv(socket_id, resp_buf, sizeof(resp_buf) - 1, 0);
130
131 if (recv_len == -1) {
132 FAIL("Socket recv() failed: %s", strerror(errno));
133 return;
134 }
135 HFTEST_LOG("Packet with length %d received.", recv_len);
136
137 EXPECT_EQ(recv_len, send_len);
138 EXPECT_EQ(memcmp(send_buf, resp_buf, send_len), 0);
139
140 EXPECT_EQ(close(socket_id), 0);
141 rmmod_hafnium();
142}