diff --git a/junos/vlans.nix b/junos/vlans.nix
new file mode 100644
index 0000000..805c7fb
--- /dev/null
+++ b/junos/vlans.nix
@@ -0,0 +1,74 @@
+{ lib, config, ... }:
+with lib;
+let
+ vlan =
+ { name, config, ... }:
+ {
+ options = {
+ id = mkOption {
+ type = types.nullOr types.ints.unsigned;
+ default = null;
+ };
+ id-list = mkOption {
+ type =
+ let
+ range_type =
+ { config, ... }:
+ {
+ config.__toString = _: "${toString config.begin}-${toString config.end}";
+ options = {
+ begin = mkOption { type = types.ints.unsigned; };
+ end = mkOption { type = types.ints.unsigned; };
+ __toString = mkOption {
+ visible = false;
+ internal = true;
+ readOnly = true;
+ type = types.unspecified;
+ };
+ };
+ };
+ in
+ types.listOf (types.either types.ints.unsigned (types.submodule range_type));
+ default = [ ];
+ };
+ l3-interface = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ };
+ xml = mkOption {
+ type = types.str;
+ readOnly = true;
+ visible = false;
+ };
+ };
+ config.xml =
+ let
+ id = optionalString (!isNull config.id) "${toString config.id}";
+ id-list = concatStringsSep "" (map (vlan: "${toString vlan}") config.id-list);
+ l3-intf = optionalString (
+ !isNull config.l3-interface
+ ) "${config.l3-interface}";
+ in
+ ''
+
+ ${name}
+ ${id}${id-list}${l3-intf}
+
+ '';
+ };
+in
+{
+ options = {
+ vlans = mkOption { type = types.attrsOf (types.submodule vlan); };
+ netconf.xmls.vlans = mkOption {
+ type = types.str;
+ visible = false;
+ readOnly = true;
+ };
+ };
+ config.netconf.xmls.vlans = ''
+
+ ${builtins.concatStringsSep "" (attrsets.mapAttrsToList (_: vlan: vlan.xml) config.vlans)}
+
+ '';
+}