diff --git a/src/build/config/BUILDCONFIG.gn b/src/build/config/BUILDCONFIG.gn
index 26fad5adf9..7a03cb09f1 100644
--- a/src/build/config/BUILDCONFIG.gn
+++ b/src/build/config/BUILDCONFIG.gn
@@ -274,6 +274,8 @@ if (target_os == "android") {
   _default_toolchain = "//build/toolchain/aix:$target_cpu"
 } else if (target_os == "zos") {
   _default_toolchain = "//build/toolchain/zos:$target_cpu"
+} else if (target_os == "openwrt") {
+  _default_toolchain = "//build/toolchain/openwrt:$target_cpu"
 } else {
   assert(false, "Unsupported target_os: $target_os")
 }
@@ -308,7 +310,7 @@ is_android = current_os == "android"
 is_chromeos = current_os == "chromeos"
 is_fuchsia = current_os == "fuchsia"
 is_ios = current_os == "ios"
-is_linux = current_os == "linux"
+is_linux = current_os == "linux" || current_os == "openwrt"
 is_mac = current_os == "mac"
 is_nacl = current_os == "nacl"
 is_win = current_os == "win" || current_os == "winuwp"
diff --git a/src/build/config/compiler/BUILD.gn b/src/build/config/compiler/BUILD.gn
index 4e8f218ab3..6fa7fa191d 100644
--- a/src/build/config/compiler/BUILD.gn
+++ b/src/build/config/compiler/BUILD.gn
@@ -303,6 +303,9 @@ config("compiler") {
     configs += [ "//build/config/android:compiler" ]
   } else if (is_linux || is_chromeos) {
     configs += [ "//build/config/linux:compiler" ]
+    if (current_os == "openwrt") {
+      configs += [ "//build/config/openwrt:compiler" ]
+    }
   } else if (is_nacl) {
     configs += [ "//build/config/nacl:compiler" ]
   } else if (is_mac) {
@@ -1203,7 +1206,8 @@ config("compiler_cpu_abi") {
       }
     } else if (current_cpu == "arm") {
       if (is_clang && !is_android && !is_nacl &&
-          !(is_chromeos_lacros && is_chromeos_device)) {
+          !(is_chromeos_lacros && is_chromeos_device) &&
+          current_os != "openwrt") {
         cflags += [ "--target=arm-linux-gnueabihf" ]
         ldflags += [ "--target=arm-linux-gnueabihf" ]
       }
@@ -1223,7 +1227,8 @@ config("compiler_cpu_abi") {
       }
     } else if (current_cpu == "arm64") {
       if (is_clang && !is_android && !is_nacl && !is_fuchsia &&
-          !(is_chromeos_lacros && is_chromeos_device)) {
+          !(is_chromeos_lacros && is_chromeos_device) &&
+          current_os != "openwrt") {
         cflags += [ "--target=aarch64-linux-gnu" ]
         ldflags += [ "--target=aarch64-linux-gnu" ]
       }
@@ -1232,7 +1237,7 @@ config("compiler_cpu_abi") {
       }
     } else if (current_cpu == "mipsel" && !is_nacl) {
       ldflags += [ "-Wl,--hash-style=sysv" ]
-      if (custom_toolchain == "") {
+      if (custom_toolchain == "" && current_os != "openwrt") {
         if (is_clang) {
           if (is_android) {
             cflags += [ "--target=mipsel-linux-android" ]
@@ -1379,7 +1384,7 @@ config("compiler_cpu_abi") {
     } else if (current_cpu == "mips64el") {
       cflags += [ "-D__SANE_USERSPACE_TYPES__" ]
       ldflags += [ "-Wl,--hash-style=sysv" ]
-      if (custom_toolchain == "") {
+      if (custom_toolchain == "" && current_os != "openwrt") {
         if (is_clang) {
           if (is_android) {
             cflags += [ "--target=mips64el-linux-android" ]
@@ -1487,7 +1492,7 @@ config("compiler_cpu_abi") {
         ldflags += [ "-m64" ]
       }
     } else if (current_cpu == "riscv64") {
-      if (is_clang && !is_android) {
+      if (is_clang && !is_android && current_os != "openwrt") {
         cflags += [ "--target=riscv64-linux-gnu" ]
         ldflags += [ "--target=riscv64-linux-gnu" ]
       }
diff --git a/src/build/config/openwrt/BUILD.gn b/src/build/config/openwrt/BUILD.gn
new file mode 100644
index 0000000000..7ad8ede3e7
--- /dev/null
+++ b/src/build/config/openwrt/BUILD.gn
@@ -0,0 +1,86 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/c++/c++.gni")
+import("//build/config/compiler/compiler.gni")
+import("//build/config/sanitizers/sanitizers.gni")
+
+if (current_toolchain == default_toolchain) {
+  import("//build/toolchain/concurrent_links.gni")
+}
+
+assert(current_os == "openwrt")
+
+declare_args() {
+  build_static = false
+
+  no_madvise_syscall = false
+}
+
+# This is included by reference in the //build/config/compiler config that
+# is applied to all targets. It is here to separate out the logic that is
+# Android-only.
+config("compiler") {
+  cflags = []
+  ldflags = []
+
+  defines = [
+    "_LIBCPP_HAS_MUSL_LIBC",
+    "__UCLIBC__",
+    "__MUSL__",
+  ]
+
+  if (build_static) {
+    # Musl static objects are not built with -fPIC, cannot use -static-pie.
+    ldflags += [ "-static" ]
+  } else if (current_cpu == "x86") {
+    ldflags += [ "-Wl,--dynamic-linker=/lib/ld-musl-i386.so.1" ]
+  } else if (current_cpu == "mipsel") {
+    ldflags += [ "-Wl,--dynamic-linker=/lib/ld-musl-mipsel-sf.so.1" ]
+  }
+
+  if (no_madvise_syscall) {
+    defines += [ "NO_MADVISE_SYSCALL" ]
+  }
+
+  abi = "musl"
+  if (current_cpu == "arm") {
+    abi = "musleabi"
+    arch = "arm"
+  } else if (current_cpu == "arm64") {
+    arch = "aarch64"
+  } else if (current_cpu == "x86") {
+    arch = "i486"
+  } else if (current_cpu == "x64") {
+    arch = "x86_64"
+  } else if (current_cpu == "mipsel") {
+    arch = "mipsel"
+  } else if (current_cpu == "mips64el") {
+    arch = "mips64el"
+  } else if (current_cpu == "riscv64") {
+    arch = "riscv64"
+  } else {
+    assert(false, "Architecture not supported")
+  }
+  cflags += [
+    "--target=$arch-openwrt-linux-$abi",
+
+    # musl malloc() alignment is 4*sizeof(size_t), i.e.
+    # 16 bytes on 32-bit CPUs, and 32 bytes on 64-bit CPUs. See
+    # https://git.musl-libc.org/cgit/musl/tree/src/malloc/oldmalloc/malloc_impl.h
+    # And https://www.openwall.com/lists/musl/2019/07/07/2 for its rationale.
+    # But Clang is unaware of this information and produces
+    #   #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 4U
+    # for the i486-openwrt-linux-musl target.
+    # This further causes static_asserts in
+    # src/third_party/protobuf/src/google/protobuf/arenastring.cc to fail.
+    # However, PartitionAlloc does not support larger than 16 alignment.
+    "-fnew-alignment=16",
+  ]
+  ldflags += [ "--target=$arch-openwrt-linux-$abi" ]
+
+  # Assign any flags set for the C compiler to asmflags so that they are sent
+  # to the assembler.
+  asmflags = cflags
+}
diff --git a/src/build/toolchain/openwrt/BUILD.gn b/src/build/toolchain/openwrt/BUILD.gn
new file mode 100644
index 0000000000..d05b4503d7
--- /dev/null
+++ b/src/build/toolchain/openwrt/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/sysroot.gni")
+import("//build/toolchain/gcc_toolchain.gni")
+
+assert(target_os == "openwrt")
+
+clang_toolchain(target_cpu) {
+  toolchain_args = {
+    current_cpu = target_cpu
+    current_os = "openwrt"
+  }
+}