1 /* 2 * Copyright (C) 2020 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 #include <sys/socket.h> 18 #include <unistd.h> 19 20 // Needs to be included after sys/socket.h 21 #include <linux/vm_sockets.h> 22 23 #include <iostream> 24 #include <optional> 25 26 #include "android-base/file.h" 27 #include "android-base/logging.h" 28 #include "android-base/parseint.h" 29 #include "android-base/unique_fd.h" 30 #include "virt/VirtualizationTest.h" 31 32 using namespace android::base; 33 using namespace android::os; 34 35 namespace virt { 36 37 static constexpr int kGuestPort = 45678; 38 static constexpr const char kVmConfigPath[] = "/data/local/tmp/virt-test/vsock_config.json"; 39 static constexpr const char kTestMessage[] = "HelloWorld"; 40 41 TEST_F(VirtualizationTest, TestVsock) { 42 binder::Status status; 43 44 unique_fd server_fd(TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM, 0))); 45 ASSERT_GE(server_fd, 0) << strerror(errno); 46 47 struct sockaddr_vm server_sa = (struct sockaddr_vm){ 48 .svm_family = AF_VSOCK, 49 .svm_port = kGuestPort, 50 .svm_cid = VMADDR_CID_ANY, 51 }; 52 53 int ret = TEMP_FAILURE_RETRY(bind(server_fd, (struct sockaddr *)&server_sa, sizeof(server_sa))); 54 ASSERT_EQ(ret, 0) << strerror(errno); 55 56 LOG(INFO) << "Listening on port " << kGuestPort << "..."; 57 ret = TEMP_FAILURE_RETRY(listen(server_fd, 1)); 58 ASSERT_EQ(ret, 0) << strerror(errno); 59 60 sp<IVirtualMachine> vm; 61 unique_fd vm_config_fd(open(kVmConfigPath, O_RDONLY | O_CLOEXEC)); 62 status = 63 mVirtManager->startVm(ParcelFileDescriptor(std::move(vm_config_fd)), std::nullopt, &vm); 64 ASSERT_TRUE(status.isOk()) << "Error starting VM: " << status; 65 66 int32_t cid; 67 status = vm->getCid(&cid); 68 ASSERT_TRUE(status.isOk()) << "Error getting CID: " << status; 69 LOG(INFO) << "VM starting with CID " << cid; 70 71 LOG(INFO) << "Accepting connection..."; 72 struct sockaddr_vm client_sa; 73 socklen_t client_sa_len = sizeof(client_sa); 74 unique_fd client_fd( 75 TEMP_FAILURE_RETRY(accept(server_fd, (struct sockaddr *)&client_sa, &client_sa_len))); 76 ASSERT_GE(client_fd, 0) << strerror(errno); 77 LOG(INFO) << "Connection from CID " << client_sa.svm_cid << " on port " << client_sa.svm_port; 78 79 LOG(INFO) << "Reading message from the client..."; 80 std::string msg; 81 ASSERT_TRUE(ReadFdToString(client_fd, &msg)); 82 83 LOG(INFO) << "Received message: " << msg; 84 ASSERT_EQ(msg, kTestMessage); 85 } 86 87 } // namespace virt 88