blob: d98d412db695f49bae5e700550fda788c9ae1eaa [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{
58 EXPECT_EQ(delete_module("hafnium", 0), 0);
59}
60
Fuad Tabbabfa42bc2019-08-06 13:45:50 +010061/**
62 * Loads and unloads the Hafnium kernel module.
63 */
Andrew Walbranbc342d42019-02-05 16:56:02 +000064TEST(linux, load_hafnium)
65{
66 insmod_hafnium();
67 rmmod_hafnium();
68}
Fuad Tabbabfa42bc2019-08-06 13:45:50 +010069
70/**
71 * Uses the kernel module to send a socket message from the primary VM to a
72 * secondary VM and echoes it back to the primary.
73 */
74TEST(linux, socket_echo_hafnium)
75{
76 spci_vm_id_t vm_id = HF_VM_ID_OFFSET + 1;
77 int port = 10;
78 int socket_id;
79 struct hf_sockaddr addr;
80 const char send_buf[] = "The quick brown fox jumps over the lazy dogs.";
81 size_t send_len = strlen(send_buf);
82 char resp_buf[MAX_BUF_SIZE];
83 ssize_t recv_len;
84
85 ASSERT_LT(send_len, MAX_BUF_SIZE);
86
87 insmod_hafnium();
88
89 /* Create Hafnium socket. */
90 socket_id = socket(PF_HF, SOCK_DGRAM, 0);
91 if (socket_id == -1) {
92 FAIL("Socket creation failed: %s", strerror(errno));
93 return;
94 }
95 HFTEST_LOG("Socket created successfully.");
96
97 /* Connect to requested VM & port. */
98 addr.family = PF_HF;
99 addr.vm_id = vm_id;
100 addr.port = port;
101 if (connect(socket_id, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
102 FAIL("Socket connection failed: %s", strerror(errno));
103 return;
104 }
105 HFTEST_LOG("Socket to secondary VM %d connected on port %d.", vm_id,
106 port);
107
108 /*
109 * Send a message to the secondary VM.
110 * Enable the confirm flag to try again in case port is busy.
111 */
112 if (send(socket_id, send_buf, send_len, MSG_CONFIRM) < 0) {
113 FAIL("Socket send() failed: %s", strerror(errno));
114 return;
115 }
116 HFTEST_LOG("Packet with length %d sent.", send_len);
117
118 /* Receive a response, which should be an echo of the sent packet. */
119 recv_len = recv(socket_id, resp_buf, sizeof(resp_buf) - 1, 0);
120
121 if (recv_len == -1) {
122 FAIL("Socket recv() failed: %s", strerror(errno));
123 return;
124 }
125 HFTEST_LOG("Packet with length %d received.", recv_len);
126
127 EXPECT_EQ(recv_len, send_len);
128 EXPECT_EQ(memcmp(send_buf, resp_buf, send_len), 0);
129
130 EXPECT_EQ(close(socket_id), 0);
131 rmmod_hafnium();
132}