diff --git a/data/templates/snmp/etc.snmpd.conf.tmpl b/data/templates/snmp/etc.snmpd.conf.tmpl
index 30806ce8a..ca9b4d617 100644
--- a/data/templates/snmp/etc.snmpd.conf.tmpl
+++ b/data/templates/snmp/etc.snmpd.conf.tmpl
@@ -1,119 +1,124 @@
 ### Autogenerated by snmp.py ###
 
 # non configurable defaults
 sysObjectID 1.3.6.1.4.1.44641
 sysServices 14
 master agentx
 agentXPerms 0777 0777
 pass .1.3.6.1.2.1.31.1.1.1.18 /opt/vyatta/sbin/if-mib-alias
 smuxpeer .1.3.6.1.2.1.83
 smuxpeer .1.3.6.1.2.1.157
 smuxsocket localhost
 
 # linkUp/Down configure the Event MIB tables to monitor
 # the ifTable for network interfaces being taken up or down
 # for making internal queries to retrieve any necessary information
 iquerySecName {{ vyos_user }}
 
 # Modified from the default linkUpDownNotification
 # to include more OIDs and poll more frequently
 notificationEvent  linkUpTrap    linkUp   ifIndex ifDescr ifType ifAdminStatus ifOperStatus
 notificationEvent  linkDownTrap  linkDown ifIndex ifDescr ifType ifAdminStatus ifOperStatus
 monitor  -r 10 -e linkUpTrap   "Generate linkUp" ifOperStatus != 2
 monitor  -r 10 -e linkDownTrap "Generate linkDown" ifOperStatus == 2
 
 # Remove all old ifTable entries with the same ifName as newly appeared
 # interface (with different ifIndex) - this is the case on e.g. ppp interfaces
 interface_replace_old yes
 
 ########################
 # configurable section #
 ########################
 
 # Default system description is VyOS version
 sysDescr VyOS {{ version }}
 
 {% if description %}
 # Description
 SysDescr {{ description }}
 {% endif %}
 
 # Listen
 agentaddress unix:/run/snmpd.socket{% if listen_on %}{% for li in listen_on %},{{ li }}{% endfor %}{% else %},{{protocol}}:161{% if ipv6_enabled %},{{protocol}}6:161{% endif %}{% endif %}
 
 # SNMP communities
 {% for c in communities %}
 {%   if c.network_v4 %}
 {%     for network in c.network_v4 %}
 {{ c.authorization }}community {{ c.name }} {{ network }}
 {%     endfor %}
 {%   elif not c.has_source %}
 {{ c.authorization }}community {{ c.name }}
 {%   endif %}
 {%   if c.network_v6 %}
 {%     for network in c.network_v6 %}
 {{ c.authorization }}community6 {{ c.name }} {{ network }}
 {%     endfor %}
 {%   elif not c.has_source %}
 {{ c.authorization }}community6 {{ c.name }}
 {%   endif %}
 {% endfor %}
 
 {% if contact %}
 # system contact information
 SysContact {{ contact }}
 {% endif %}
 
 {% if location %}
 # system location information
 SysLocation {{ location }}
 {% endif %}
 
 {% if smux_peers %}
 # additional smux peers
 {%   for sp in smux_peers %}
 smuxpeer {{ sp }}
 {%   endfor %}
 {% endif %}
 
 {% if trap_targets %}
 # if there is a problem - tell someone!
 {%   for trap in trap_targets %}
 trap2sink {{ trap.target }}{{ ":" + trap.port if trap.port is defined }} {{ trap.community }}
 {%   endfor %}
 {% endif %}
 
 {% if v3_enabled %}
 #
 # SNMPv3 stuff goes here
 #
 # views
 {%   for view in v3_views %}
 {%     for oid in view.oids %}
 view {{ view.name }} included .{{ oid.oid }}
+{%         if oid.exclude %}
+{%             for excl in oid.exclude %}
+view {{ view.name }} excluded .{{ excl }}
+{%             endfor %}
+{%         endif %}
 {%     endfor %}
 {%   endfor %}
 
 # access
 #             context sec.model sec.level match  read    write  notif
 {%   for group in v3_groups %}
 access {{ group.name }} "" usm {{ group.seclevel }} exact {{ group.view }} {% if group.mode == 'ro' %}none{% else %}{{ group.view }}{% endif %} none
 {%   endfor %}
 
 # trap-target
 {%   for t in v3_traps %}
 trapsess -v 3 {{ '-Ci' if t.type == 'inform' }} -e {{ v3_engineid }} -u {{ t.secName }} -l {{ t.secLevel }} -a {{ t.authProtocol }} {% if t.authPassword %}-A {{ t.authPassword }}{% elif t.authMasterKey %}-3m {{ t.authMasterKey }}{% endif %} -x {{ t.privProtocol }} {% if t.privPassword %}-X {{ t.privPassword }}{% elif t.privMasterKey %}-3M {{ t.privMasterKey }}{% endif %} {{ t.ipProto }}:{{ t.ipAddr }}:{{ t.ipPort }}
 {%   endfor %}
 
 # group
 {%   for u in v3_users %}
 group {{ u.group }} usm {{ u.name }}
 {%   endfor %}
 {% endif %}
 
 {% if script_ext %}
 # extension scripts
 {%   for ext in script_ext|sort(attribute='name') %}
 extend {{ ext.name }} {{ ext.script }}
 {%   endfor %}
 {% endif %}
diff --git a/interface-definitions/snmp.xml.in b/interface-definitions/snmp.xml.in
index 1067aa8a8..48aee7c9a 100644
--- a/interface-definitions/snmp.xml.in
+++ b/interface-definitions/snmp.xml.in
@@ -1,654 +1,655 @@
 <?xml version="1.0"?>
 <!-- SNMP forwarder configuration -->
 <interfaceDefinition>
   <node name="service">
     <children>
       <node name="snmp" owner="${vyos_conf_scripts_dir}/snmp.py">
         <properties>
           <help>Simple Network Management Protocol (SNMP)</help>
           <priority>900</priority>
         </properties>
         <children>
           <tagNode name="community">
             <properties>
               <help>Community name</help>
               <constraint>
                 <regex>^[a-zA-Z0-9\-_!@*#]{1,100}$</regex>
               </constraint>
               <constraintErrorMessage>Community string is limited to alphanumerical characters, !, @, * and # with a total lenght of 100</constraintErrorMessage>
             </properties>
             <children>
               <leafNode name="authorization">
                 <properties>
                   <help>Authorization type (default: 'ro')</help>
                   <completionHelp>
                     <list>ro rw</list>
                   </completionHelp>
                   <valueHelp>
                     <format>ro</format>
                     <description>read only</description>
                   </valueHelp>
                   <valueHelp>
                     <format>rw</format>
                     <description>read write</description>
                   </valueHelp>
                   <constraint>
                     <regex>^(ro|rw)$</regex>
                   </constraint>
                   <constraintErrorMessage>Authorization type must be either 'rw' or 'ro'</constraintErrorMessage>
                 </properties>
               </leafNode>
               <leafNode name="client">
                 <properties>
                   <help>IP address of SNMP client allowed to contact system</help>
                   <constraint>
                     <validator name="ipv4-address"/>
                     <validator name="ipv6-address"/>
                   </constraint>
                   <multi/>
                 </properties>
               </leafNode>
               <leafNode name="network">
                 <properties>
                   <help>Subnet of SNMP client(s) allowed to contact system</help>
                   <valueHelp>
                     <format>ipv4net</format>
                     <description>IP address and prefix length</description>
                   </valueHelp>
                   <valueHelp>
                     <format>ipv6net</format>
                     <description>IPv6 address and prefix length</description>
                   </valueHelp>
                   <constraint>
                     <validator name="ip-prefix"/>
                   </constraint>
                   <multi/>
                 </properties>
               </leafNode>
             </children>
           </tagNode>
           <leafNode name="contact">
             <properties>
               <help>Contact information</help>
               <constraint>
                 <regex>^.{1,255}$</regex>
               </constraint>
               <constraintErrorMessage>Contact information is limited to 255 characters or less</constraintErrorMessage>
             </properties>
           </leafNode>
           <leafNode name="description">
             <properties>
               <help>Description information</help>
               <constraint>
                 <regex>^.{1,255}$</regex>
               </constraint>
               <constraintErrorMessage>Description is limited to 255 characters or less</constraintErrorMessage>
             </properties>
           </leafNode>
           <tagNode name="listen-address">
             <properties>
               <help>IP address to listen for incoming SNMP requests</help>
               <completionHelp>
                 <script>${vyos_completion_dir}/list_local_ips.sh --both</script>
               </completionHelp>
               <valueHelp>
                 <format>ipv4</format>
                 <description>IPv4 address to listen for incoming SNMP requests</description>
               </valueHelp>
               <valueHelp>
                 <format>ipv6</format>
                 <description>IPv6 address to listen for incoming SNMP requests</description>
               </valueHelp>
               <constraint>
                 <validator name="ipv4-address"/>
                 <validator name="ipv6-address"/>
               </constraint>
             </properties>
             <children>
               <leafNode name="port">
                 <properties>
                   <help>Port for SNMP service (default: '161')</help>
                   <valueHelp>
                     <format>u32:1-65535</format>
                     <description>Numeric IP port</description>
                   </valueHelp>
                   <constraint>
                     <validator name="numeric" argument="--range 1-65535"/>
                   </constraint>
                   <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage>
                 </properties>
               </leafNode>
             </children>
           </tagNode>
           <leafNode name="location">
             <properties>
               <help>Location information</help>
               <constraint>
                 <regex>^.{1,255}$</regex>
               </constraint>
               <constraintErrorMessage>Location is limited to 255 characters or less</constraintErrorMessage>
             </properties>
           </leafNode>
           <leafNode name="protocol">
             <properties>
               <help>Listen protocol for SNMP</help>
               <completionHelp>
                 <list>udp tcp</list>
               </completionHelp>
               <valueHelp>
                 <format>udp</format>
                 <description>Listen protocol UDP (default)</description>
               </valueHelp>
               <valueHelp>
                 <format>tcp</format>
                 <description>Listen protocol TCP</description>
               </valueHelp>
               <constraint>
                 <regex>^(udp|tcp)$</regex>
               </constraint>
             </properties>
             <defaultValue>udp</defaultValue>
           </leafNode>
           <leafNode name="smux-peer">
             <properties>
               <help>Register a subtree for SMUX-based processing</help>
               <valueHelp>
                 <format>oid</format>
                 <description>Object Identifier</description>
               </valueHelp>
               <multi/>
             </properties>
           </leafNode>
           <leafNode name="trap-source">
             <properties>
               <help>SNMP trap source address</help>
               <valueHelp>
                 <format>ipv4</format>
                 <description>IPv4 address</description>
               </valueHelp>
               <valueHelp>
                 <format>ipv6</format>
                 <description>IPv6 address</description>
               </valueHelp>
               <constraint>
                 <validator name="ipv4-address"/>
                 <validator name="ipv6-address"/>
               </constraint>
             </properties>
           </leafNode>
           <tagNode name="trap-target">
             <properties>
               <help>Address of trap target</help>
               <valueHelp>
                 <format>ipv4</format>
                 <description>IPv4 address</description>
               </valueHelp>
               <valueHelp>
                 <format>ipv6</format>
                 <description>IPv6 address</description>
               </valueHelp>
               <constraint>
                 <validator name="ipv4-address"/>
                 <validator name="ipv6-address"/>
               </constraint>
             </properties>
             <children>
               <leafNode name="community">
                 <properties>
                   <help>Community used when sending trap information</help>
                 </properties>
               </leafNode>
               <leafNode name="port">
                 <properties>
                   <help>Destination port used for trap notification</help>
                   <valueHelp>
                     <format>u32:1-65535</format>
                     <description>Numeric IP port</description>
                   </valueHelp>
                   <constraint>
                     <validator name="numeric" argument="--range 1-65535"/>
                   </constraint>
                   <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage>
                 </properties>
               </leafNode>
             </children>
           </tagNode>
           <node name="v3">
             <properties>
               <help>Simple Network Management Protocol (SNMP) v3</help>
             </properties>
             <children>
               <leafNode name="engineid">
                 <properties>
                   <help>Specifies the EngineID that uniquely identify an agent (e.g. 000000000000000000000002)</help>
                   <constraint>
                     <regex>^([0-9a-f][0-9a-f]){1,18}$</regex>
                   </constraint>
                   <constraintErrorMessage>ID must contain an even number (from 2 to 36) of hex digits</constraintErrorMessage>
                 </properties>
               </leafNode>
               <tagNode name="group">
                 <properties>
                   <help>Specifies the group with name groupname</help>
                 </properties>
                 <children>
                   <leafNode name="mode">
                     <properties>
                       <help>Define group access permission (default: 'ro')</help>
                       <completionHelp>
                         <list>ro rw</list>
                       </completionHelp>
                       <valueHelp>
                         <format>ro</format>
                         <description>read only</description>
                       </valueHelp>
                       <valueHelp>
                         <format>rw</format>
                         <description>read write</description>
                       </valueHelp>
                       <constraint>
                         <regex>^(ro|rw)$</regex>
                       </constraint>
                       <constraintErrorMessage>Authorization type must be either 'rw' or 'ro'</constraintErrorMessage>
                     </properties>
                   </leafNode>
                   <leafNode name="seclevel">
                     <properties>
                       <help>Security levels</help>
                       <completionHelp>
                         <list>noauth auth priv</list>
                       </completionHelp>
                       <valueHelp>
                         <format>noauth</format>
                         <description>Messages not authenticated and not encrypted (noAuthNoPriv)</description>
                       </valueHelp>
                       <valueHelp>
                         <format>auth</format>
                         <description>Messages are authenticated but not encrypted (authNoPriv)</description>
                       </valueHelp>
                       <valueHelp>
                         <format>priv</format>
                         <description>Messages are authenticated and encrypted (authPriv)</description>
                       </valueHelp>
                       <constraint>
                         <regex>^(noauth|auth|priv)$</regex>
                       </constraint>
                     </properties>
                   </leafNode>
                   <leafNode name="view">
                     <properties>
                       <help>Defines the name of view</help>
                       <completionHelp>
                         <path>service snmp v3 view</path>
                       </completionHelp>
                     </properties>
                   </leafNode>
                 </children>
               </tagNode>
               <tagNode name="trap-target">
                 <properties>
                   <help>Defines SNMP target for inform or traps for IP</help>
                   <valueHelp>
                     <format>ipv4</format>
                     <description>IP address of trap target</description>
                   </valueHelp>
                   <valueHelp>
                     <format>ipv6</format>
                     <description>IPv6 address of trap target</description>
                   </valueHelp>
                   <constraint>
                     <validator name="ipv4-address"/>
                     <validator name="ipv6-address"/>
                   </constraint>
                 </properties>
                 <children>
                   <node name="auth">
                     <properties>
                       <help>Defines the privacy</help>
                     </properties>
                     <children>
                       <leafNode name="encrypted-password">
                         <properties>
                           <help>Defines the encrypted key for authentication</help>
                           <constraint>
                             <regex>^[0-9a-f]*$</regex>
                           </constraint>
                           <constraintErrorMessage>Encrypted key must only contain hex digits</constraintErrorMessage>
                         </properties>
                       </leafNode>
                       <leafNode name="plaintext-password">
                         <properties>
                           <help>Defines the clear text key for authentication</help>
                           <constraint>
                             <regex>^.{8,}$</regex>
                           </constraint>
                           <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage>
                         </properties>
                       </leafNode>
                       <leafNode name="type">
                         <properties>
                           <help>Defines the protocol used for authentication (default: 'md5')</help>
                           <completionHelp>
                             <list>md5 sha</list>
                           </completionHelp>
                           <valueHelp>
                             <format>md5</format>
                             <description>Message Digest 5</description>
                           </valueHelp>
                           <valueHelp>
                             <format>sha</format>
                             <description>Secure Hash Algorithm</description>
                           </valueHelp>
                           <constraint>
                             <regex>^(md5|sha)$</regex>
                           </constraint>
                         </properties>
                       </leafNode>
                     </children>
                   </node>
                   <leafNode name="port">
                     <properties>
                       <help>Specifies TCP/UDP port of destination SNMP traps/informs (default: '162')</help>
                       <valueHelp>
                         <format>u32:1-65535</format>
                         <description>Numeric IP port</description>
                       </valueHelp>
                       <constraint>
                         <validator name="numeric" argument="--range 1-65535"/>
                       </constraint>
                       <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage>
                     </properties>
                   </leafNode>
                   <node name="privacy">
                     <properties>
                       <help>Defines the privacy</help>
                     </properties>
                     <children>
                       <leafNode name="encrypted-password">
                         <properties>
                           <help>Defines the encrypted key for privacy protocol</help>
                           <constraint>
                             <regex>^[0-9a-f]*$</regex>
                           </constraint>
                           <constraintErrorMessage>Encrypted key must only contain hex digits</constraintErrorMessage>
                         </properties>
                       </leafNode>
                       <leafNode name="plaintext-password">
                         <properties>
                           <help>Defines the clear text key for privacy protocol</help>
                           <constraint>
                             <regex>^.{8,}$</regex>
                           </constraint>
                           <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage>
                         </properties>
                       </leafNode>
                       <leafNode name="type">
                         <properties>
                           <help>Defines the protocol for privacy (default: 'des')</help>
                           <completionHelp>
                             <list>des aes</list>
                           </completionHelp>
                           <valueHelp>
                             <format>des</format>
                             <description>Data Encryption Standard</description>
                           </valueHelp>
                           <valueHelp>
                             <format>aes</format>
                             <description>Advanced Encryption Standard</description>
                           </valueHelp>
                           <constraint>
                             <regex>^(des|aes)$</regex>
                           </constraint>
                         </properties>
                       </leafNode>
                     </children>
                   </node>
                   <leafNode name="protocol">
                     <properties>
                       <help>Defines protocol for notification between TCP and UDP</help>
                       <completionHelp>
                         <list>tcp udp</list>
                       </completionHelp>
                       <valueHelp>
                         <format>tcp</format>
                         <description>Use Transmission Control Protocol for notifications</description>
                       </valueHelp>
                       <valueHelp>
                         <format>udp</format>
                         <description>Use User Datagram Protocol for notifications</description>
                       </valueHelp>
                       <constraint>
                         <regex>^(tcp|udp)$</regex>
                       </constraint>
                     </properties>
                   </leafNode>
                   <leafNode name="type">
                     <properties>
                       <help>Specifies the type of notification between inform and trap (default: 'inform')</help>
                       <completionHelp>
                         <list>inform trap</list>
                       </completionHelp>
                       <valueHelp>
                         <format>inform</format>
                         <description>Use INFORM</description>
                       </valueHelp>
                       <valueHelp>
                         <format>trap</format>
                         <description>Use TRAP</description>
                       </valueHelp>
                       <constraint>
                         <regex>^(inform|trap)$</regex>
                       </constraint>
                     </properties>
                   </leafNode>
                   <leafNode name="user">
                     <properties>
                       <help>Defines username for authentication</help>
                       <completionHelp>
                         <path>service snmp v3 user</path>
                       </completionHelp>
                     </properties>
                   </leafNode>
                 </children>
               </tagNode>
               <tagNode name="user">
                 <properties>
                   <help>Specifies the user with name username</help>
                   <constraint>
                     <regex>[^\(\)\|\-]+$</regex>
                   </constraint>
                   <constraintErrorMessage>Illegal characters in name</constraintErrorMessage>
                 </properties>
                 <children>
                   <node name="auth">
                     <properties>
                       <help>Specifies the auth</help>
                     </properties>
                     <children>
                       <leafNode name="encrypted-password">
                         <properties>
                           <help>Defines the encrypted key for authentication</help>
                           <constraint>
                             <regex>^[0-9a-f]*$</regex>
                           </constraint>
                           <constraintErrorMessage>Encrypted key must only contain hex digits</constraintErrorMessage>
                         </properties>
                       </leafNode>
                       <leafNode name="plaintext-password">
                         <properties>
                           <help>Defines the clear text key for authentication</help>
                           <constraint>
                             <regex>^.{8,}$</regex>
                           </constraint>
                           <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage>
                         </properties>
                       </leafNode>
                       <leafNode name="type">
                         <properties>
                           <help>Defines the protocol used for authentication (default: 'md5')</help>
                           <completionHelp>
                             <list>md5 sha</list>
                           </completionHelp>
                           <valueHelp>
                             <format>md5</format>
                             <description>Message Digest 5</description>
                           </valueHelp>
                           <valueHelp>
                             <format>sha</format>
                             <description>Secure Hash Algorithm</description>
                           </valueHelp>
                           <constraint>
                             <regex>^(md5|sha)$</regex>
                           </constraint>
                         </properties>
                       </leafNode>
                     </children>
                   </node>
                   <leafNode name="group">
                     <properties>
                       <help>Specifies group for user name</help>
                       <completionHelp>
                         <path>service snmp v3 group</path>
                       </completionHelp>
                     </properties>
                   </leafNode>
                   <leafNode name="mode">
                     <properties>
                       <help>Define users access permission (default: 'ro')</help>
                       <completionHelp>
                         <list>ro rw</list>
                       </completionHelp>
                       <valueHelp>
                         <format>ro</format>
                         <description>read only</description>
                       </valueHelp>
                       <valueHelp>
                         <format>rw</format>
                         <description>read write</description>
                       </valueHelp>
                       <constraint>
                         <regex>^(ro|rw)$</regex>
                       </constraint>
                       <constraintErrorMessage>Authorization type must be either 'rw' or 'ro'</constraintErrorMessage>
                     </properties>
                   </leafNode>
                   <node name="privacy">
                     <properties>
                       <help>Defines the privacy</help>
                     </properties>
                     <children>
                       <leafNode name="encrypted-password">
                         <properties>
                           <help>Defines the encrypted key for privacy protocol</help>
                           <constraint>
                             <regex>^[0-9a-f]*$</regex>
                           </constraint>
                           <constraintErrorMessage>Encrypted key must only contain hex digits</constraintErrorMessage>
                         </properties>
                       </leafNode>
                       <leafNode name="plaintext-password">
                         <properties>
                           <help>Defines the clear text key for privacy protocol</help>
                           <constraint>
                             <regex>^.{8,}$</regex>
                           </constraint>
                           <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage>
                         </properties>
                       </leafNode>
                       <leafNode name="type">
                         <properties>
                           <help>Defines the protocol for privacy (default: 'des')</help>
                           <completionHelp>
                             <list>des aes</list>
                           </completionHelp>
                           <valueHelp>
                             <format>des</format>
                             <description>Data Encryption Standard</description>
                           </valueHelp>
                           <valueHelp>
                             <format>aes</format>
                             <description>Advanced Encryption Standard</description>
                           </valueHelp>
                           <constraint>
                             <regex>^(des|aes)$</regex>
                           </constraint>
                         </properties>
                       </leafNode>
                     </children>
                   </node>
                 </children>
               </tagNode>
               <tagNode name="view">
                 <properties>
                   <help>Specifies the view with name viewname</help>
                   <constraint>
                     <regex>[^\(\)\|\-]+$</regex>
                   </constraint>
                   <constraintErrorMessage>Illegal characters in name</constraintErrorMessage>
                 </properties>
                 <children>
                   <tagNode name="oid">
                     <properties>
                       <help>Specifies the oid</help>
                       <constraint>
                         <regex>^[0-9]+(\.[0-9]+)*$</regex>
                       </constraint>
                       <constraintErrorMessage>OID must start from a number</constraintErrorMessage>
                     </properties>
                     <children>
                       <leafNode name="exclude">
                         <properties>
                           <help>Exclude is an optional argument</help>
+                          <multi/>
                         </properties>
                       </leafNode>
                       <leafNode name="mask">
                         <properties>
                           <help>Defines a bit-mask that is indicating which subidentifiers of the associated subtree OID should be regarded as significant</help>
                           <constraint>
                             <regex>^[0-9a-f]{2}([\.:][0-9a-f]{2})*$</regex>
                           </constraint>
                           <constraintErrorMessage>MASK is a list of hex octets, separated by '.' or ':'</constraintErrorMessage>
                         </properties>
                       </leafNode>
                     </children>
                   </tagNode>
                 </children>
               </tagNode>
             </children>
           </node>
           <node name="script-extensions">
             <properties>
               <help>SNMP script extensions</help>
             </properties>
             <children>
               <tagNode name="extension-name">
                 <properties>
                   <help>Extension name</help>
                   <constraint>
                     <regex>^[a-z0-9\.\-\_]+</regex>
                   </constraint>
                   <constraintErrorMessage>Script extension contains invalid characters</constraintErrorMessage>
                 </properties>
                 <children>
                   <leafNode name="script">
                     <properties>
                       <help>Script location and name</help>
                       <completionHelp>
                         <script>ls /config/user-data</script>
                       </completionHelp>
                       <constraint>
                         <regex>^[a-z0-9\.\-\_\/]+</regex>
                       </constraint>
                       <constraintErrorMessage>Script extension contains invalid characters</constraintErrorMessage>
                     </properties>
                   </leafNode>
                 </children>
               </tagNode>
             </children>
           </node>
           #include <include/interface/vrf.xml.i>
         </children>
       </node>
     </children>
   </node>
 </interfaceDefinition>
diff --git a/smoketest/scripts/cli/test_service_snmp.py b/smoketest/scripts/cli/test_service_snmp.py
index 864097771..5066b7942 100755
--- a/smoketest/scripts/cli/test_service_snmp.py
+++ b/smoketest/scripts/cli/test_service_snmp.py
@@ -1,229 +1,249 @@
 #!/usr/bin/env python3
 #
 # Copyright (C) 2019-2022 VyOS maintainers and contributors
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 or later as
 # published by the Free Software Foundation.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import re
 import unittest
 
 from base_vyostest_shim import VyOSUnitTestSHIM
 
 from vyos.configsession import ConfigSessionError
 from vyos.template import is_ipv4
 from vyos.template import address_from_cidr
 from vyos.util import read_file
 from vyos.util import process_named_running
 
 PROCESS_NAME = 'snmpd'
 SNMPD_CONF = '/etc/snmp/snmpd.conf'
 
 base_path = ['service', 'snmp']
 
 def get_config_value(key):
     tmp = read_file(SNMPD_CONF)
     tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp)
     return tmp[0]
 
 class TestSNMPService(VyOSUnitTestSHIM.TestCase):
     @classmethod
     def setUpClass(cls):
         super(cls, cls).setUpClass()
 
         # ensure we can also run this test on a live system - so lets clean
         # out the current configuration :)
         cls.cli_delete(cls, base_path)
 
     def tearDown(self):
         # delete testing SNMP config
         self.cli_delete(base_path)
         self.cli_commit()
 
     def test_snmp_basic(self):
         dummy_if = 'dum7312'
         dummy_addr = '100.64.0.1/32'
         self.cli_set(['interfaces', 'dummy', dummy_if, 'address', dummy_addr])
 
         # Check if SNMP can be configured and service runs
         clients = ['192.0.2.1', '2001:db8::1']
         networks = ['192.0.2.128/25', '2001:db8:babe::/48']
         listen = ['127.0.0.1', '::1', address_from_cidr(dummy_addr)]
         port = '5000'
 
         for auth in ['ro', 'rw']:
             community = 'VyOS' + auth
             self.cli_set(base_path + ['community', community, 'authorization', auth])
             for client in clients:
                 self.cli_set(base_path + ['community', community, 'client', client])
             for network in networks:
                 self.cli_set(base_path + ['community', community, 'network', network])
 
         for addr in listen:
             self.cli_set(base_path + ['listen-address', addr, 'port', port])
 
         self.cli_set(base_path + ['contact', 'maintainers@vyos.io'])
         self.cli_set(base_path + ['location', 'qemu'])
 
         self.cli_commit()
 
         # verify listen address, it will be returned as
         # ['unix:/run/snmpd.socket,udp:127.0.0.1:161,udp6:[::1]:161']
         # thus we need to transfor this into a proper list
         config = get_config_value('agentaddress')
         expected = 'unix:/run/snmpd.socket'
         self.assertIn(expected, config)
 
         for addr in listen:
             if is_ipv4(addr):
                 expected = f'udp:{addr}:{port}'
             else:
                 expected = f'udp6:[{addr}]:{port}'
             self.assertIn(expected, config)
 
         # Check for running process
         self.assertTrue(process_named_running(PROCESS_NAME))
         self.cli_delete(['interfaces', 'dummy', dummy_if])
 
     def test_snmp_tcp(self):
         dummy_if = 'dum123'
         dummy_addr = '100.64.0.1/32'
         self.cli_set(['interfaces', 'dummy', dummy_if, 'address', dummy_addr])
 
         # Check if SNMP can be configured and service runs
         clients = ['192.0.2.1', '2001:db8::1']
         networks = ['192.0.2.128/25', '2001:db8:babe::/48']
         listen = ['127.0.0.1', '::1', address_from_cidr(dummy_addr)]
         port = '2325'
 
         for auth in ['ro', 'rw']:
             community = 'VyOS' + auth
             self.cli_set(base_path + ['community', community, 'authorization', auth])
             for client in clients:
                 self.cli_set(base_path + ['community', community, 'client', client])
             for network in networks:
                 self.cli_set(base_path + ['community', community, 'network', network])
 
         for addr in listen:
             self.cli_set(base_path + ['listen-address', addr, 'port', port])
 
         self.cli_set(base_path + ['contact', 'maintainers@vyos.io'])
         self.cli_set(base_path + ['location', 'qemu'])
         self.cli_set(base_path + ['protocol', 'tcp'])
 
         self.cli_commit()
 
         # verify listen address, it will be returned as
         # ['unix:/run/snmpd.socket,tcp:127.0.0.1:161,tcp6:[::1]:161']
         # thus we need to transfor this into a proper list
         config = get_config_value('agentaddress')
         expected = 'unix:/run/snmpd.socket'
         self.assertIn(expected, config)
 
         for addr in listen:
             if is_ipv4(addr):
                 expected = f'tcp:{addr}:{port}'
             else:
                 expected = f'tcp6:[{addr}]:{port}'
             self.assertIn(expected, config)
 
         # Check for running process
         self.assertTrue(process_named_running(PROCESS_NAME))
         self.cli_delete(['interfaces', 'dummy', dummy_if])
 
     def test_snmpv3_sha(self):
         # Check if SNMPv3 can be configured with SHA authentication
         # and service runs
 
         self.cli_set(base_path + ['v3', 'engineid', '000000000000000000000002'])
         self.cli_set(base_path + ['v3', 'group', 'default', 'mode', 'ro'])
         # check validate() - a view must be created before this can be committed
         with self.assertRaises(ConfigSessionError):
             self.cli_commit()
 
         self.cli_set(base_path + ['v3', 'view', 'default', 'oid', '1'])
         self.cli_set(base_path + ['v3', 'group', 'default', 'view', 'default'])
 
         # create user
         self.cli_set(base_path + ['v3', 'user', 'vyos', 'auth', 'plaintext-password', 'vyos12345678'])
         self.cli_set(base_path + ['v3', 'user', 'vyos', 'auth', 'type', 'sha'])
         self.cli_set(base_path + ['v3', 'user', 'vyos', 'privacy', 'plaintext-password', 'vyos12345678'])
         self.cli_set(base_path + ['v3', 'user', 'vyos', 'privacy', 'type', 'aes'])
         self.cli_set(base_path + ['v3', 'user', 'vyos', 'group', 'default'])
 
         self.cli_commit()
 
         # commit will alter the CLI values - check if they have been updated:
         hashed_password = '4e52fe55fd011c9c51ae2c65f4b78ca93dcafdfe'
         tmp = self._session.show_config(base_path + ['v3', 'user', 'vyos', 'auth', 'encrypted-password']).split()[1]
         self.assertEqual(tmp, hashed_password)
 
         tmp = self._session.show_config(base_path + ['v3', 'user', 'vyos', 'privacy', 'encrypted-password']).split()[1]
         self.assertEqual(tmp, hashed_password)
 
         # TODO: read in config file and check values
 
         # Check for running process
         self.assertTrue(process_named_running(PROCESS_NAME))
 
     def test_snmpv3_md5(self):
         # Check if SNMPv3 can be configured with MD5 authentication
         # and service runs
         snmpv3_group = 'default_group'
         snmpv3_view = 'default_view'
         snmpv3_view_oid = '1'
         snmpv3_user = 'vyos'
 
         self.cli_set(base_path + ['v3', 'engineid', '000000000000000000000002'])
 
         # create user
         self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'auth', 'plaintext-password', 'vyos12345678'])
         self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'auth', 'type', 'md5'])
         self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'privacy', 'plaintext-password', 'vyos12345678'])
         self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'privacy', 'type', 'des'])
 
         # check validate() - user requires a group to be created
         with self.assertRaises(ConfigSessionError):
             self.cli_commit()
         self.cli_set(base_path + ['v3', 'user', 'vyos', 'group', snmpv3_group])
 
         self.cli_set(base_path + ['v3', 'group', snmpv3_group, 'mode', 'ro'])
         # check validate() - a view must be created before this can be comitted
         with self.assertRaises(ConfigSessionError):
             self.cli_commit()
 
         self.cli_set(base_path + ['v3', 'view', snmpv3_view, 'oid', snmpv3_view_oid])
         self.cli_set(base_path + ['v3', 'group', snmpv3_group, 'view', snmpv3_view])
 
         self.cli_commit()
 
         # commit will alter the CLI values - check if they have been updated:
         hashed_password = '4c67690d45d3dfcd33d0d7e308e370ad'
         tmp = self._session.show_config(base_path + ['v3', 'user', 'vyos', 'auth', 'encrypted-password']).split()[1]
         self.assertEqual(tmp, hashed_password)
 
         tmp = self._session.show_config(base_path + ['v3', 'user', 'vyos', 'privacy', 'encrypted-password']).split()[1]
         self.assertEqual(tmp, hashed_password)
 
         tmp = read_file(SNMPD_CONF)
         # views
         self.assertIn(f'view {snmpv3_view} included .{snmpv3_view_oid}', tmp)
         # group
         self.assertIn(f'group {snmpv3_group} usm {snmpv3_user}', tmp)
         # access
         self.assertIn(f'access {snmpv3_group} "" usm auth exact {snmpv3_view} none none', tmp)
 
         # Check for running process
         self.assertTrue(process_named_running(PROCESS_NAME))
 
+    def test_snmpv3_view_exclude(self):
+        snmpv3_group = 'default_group'
+        snmpv3_view = 'default_view'
+        snmpv3_view_oid = '1'
+        snmpv3_view_oid_exclude = ['1.3.6.1.2.1.4.21', '1.3.6.1.2.1.4.24']
+
+        self.cli_set(base_path + ['v3', 'group', snmpv3_group, 'view', snmpv3_view])
+        self.cli_set(base_path + ['v3', 'view', snmpv3_view, 'oid', snmpv3_view_oid])
+
+        for excluded in snmpv3_view_oid_exclude:
+            self.cli_set(base_path + ['v3', 'view', snmpv3_view, 'oid', snmpv3_view_oid, 'exclude', excluded])
+
+        self.cli_commit()
+
+        tmp = read_file(SNMPD_CONF)
+        # views
+        self.assertIn(f'view {snmpv3_view} included .{snmpv3_view_oid}', tmp)
+        for excluded in snmpv3_view_oid_exclude:
+            self.assertIn(f'view {snmpv3_view} excluded .{excluded}', tmp)
+
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py
index 0be0da3d1..7b3f9cbb7 100755
--- a/src/conf_mode/snmp.py
+++ b/src/conf_mode/snmp.py
@@ -1,596 +1,598 @@
 #!/usr/bin/env python3
 #
 # Copyright (C) 2018-2022 VyOS maintainers and contributors
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 or later as
 # published by the Free Software Foundation.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import os
 
 from sys import exit
 
 from vyos.config import Config
 from vyos.configverify import verify_vrf
 from vyos.snmpv3_hashgen import plaintext_to_md5
 from vyos.snmpv3_hashgen import plaintext_to_sha1
 from vyos.snmpv3_hashgen import random
 from vyos.template import render
 from vyos.template import is_ipv4
 from vyos.util import call
 from vyos.util import chmod_755
 from vyos.validate import is_addr_assigned
 from vyos.version import get_version_data
 from vyos import ConfigError
 from vyos import airbag
 airbag.enable()
 
 config_file_client  = r'/etc/snmp/snmp.conf'
 config_file_daemon  = r'/etc/snmp/snmpd.conf'
 config_file_access  = r'/usr/share/snmp/snmpd.conf'
 config_file_user    = r'/var/lib/snmp/snmpd.conf'
 default_script_dir  = r'/config/user-data/'
 systemd_override    = r'/etc/systemd/system/snmpd.service.d/override.conf'
 
 # SNMP OIDs used to mark auth/priv type
 OIDs = {
     'md5' : '.1.3.6.1.6.3.10.1.1.2',
     'sha' : '.1.3.6.1.6.3.10.1.1.3',
     'aes' : '.1.3.6.1.6.3.10.1.2.4',
     'des' : '.1.3.6.1.6.3.10.1.2.2',
     'none': '.1.3.6.1.6.3.10.1.2.1'
 }
 
 default_config_data = {
     'listen_on': [],
     'listen_address': [],
     'ipv6_enabled': 'True',
     'communities': [],
     'smux_peers': [],
     'location' : '',
     'protocol' : 'udp',
     'description' : '',
     'contact' : '',
     'trap_source': '',
     'trap_targets': [],
     'vyos_user': '',
     'vyos_user_pass': '',
     'version': '',
     'v3_enabled': 'False',
     'v3_engineid': '',
     'v3_groups': [],
     'v3_traps': [],
     'v3_users': [],
     'v3_views': [],
     'script_ext': []
 }
 
 def rmfile(file):
     if os.path.isfile(file):
         os.unlink(file)
 
 def get_config():
     snmp = default_config_data
     conf = Config()
     if not conf.exists('service snmp'):
         return None
     else:
         if conf.exists('system ipv6 disable'):
             snmp['ipv6_enabled'] = False
 
         conf.set_level('service snmp')
 
     version_data = get_version_data()
     snmp['version'] = version_data['version']
 
     # create an internal snmpv3 user of the form 'vyosxxxxxxxxxxxxxxxx'
     snmp['vyos_user'] = 'vyos' + random(8)
     snmp['vyos_user_pass'] = random(16)
 
     if conf.exists('community'):
         for name in conf.list_nodes('community'):
             community = {
                 'name': name,
                 'authorization': 'ro',
                 'network_v4': [],
                 'network_v6': [],
                 'has_source' : False
             }
 
             if conf.exists('community {0} authorization'.format(name)):
                 community['authorization'] = conf.return_value('community {0} authorization'.format(name))
 
             # Subnet of SNMP client(s) allowed to contact system
             if conf.exists('community {0} network'.format(name)):
                 for addr in conf.return_values('community {0} network'.format(name)):
                     if is_ipv4(addr):
                         community['network_v4'].append(addr)
                     else:
                         community['network_v6'].append(addr)
 
             # IP address of SNMP client allowed to contact system
             if conf.exists('community {0} client'.format(name)):
                 for addr in conf.return_values('community {0} client'.format(name)):
                     if is_ipv4(addr):
                         community['network_v4'].append(addr)
                     else:
                         community['network_v6'].append(addr)
 
             if (len(community['network_v4']) > 0) or (len(community['network_v6']) > 0):
                  community['has_source'] = True
 
             snmp['communities'].append(community)
 
     if conf.exists('contact'):
         snmp['contact'] = conf.return_value('contact')
 
     if conf.exists('description'):
         snmp['description'] = conf.return_value('description')
 
     if conf.exists('listen-address'):
         for addr in conf.list_nodes('listen-address'):
             port = '161'
             if conf.exists('listen-address {0} port'.format(addr)):
                 port = conf.return_value('listen-address {0} port'.format(addr))
 
             snmp['listen_address'].append((addr, port))
 
         # Always listen on localhost if an explicit address has been configured
         # This is a safety measure to not end up with invalid listen addresses
         # that are not configured on this system. See https://vyos.dev/T850
         if not '127.0.0.1' in conf.list_nodes('listen-address'):
             snmp['listen_address'].append(('127.0.0.1', '161'))
 
         if not '::1' in conf.list_nodes('listen-address'):
             snmp['listen_address'].append(('::1', '161'))
 
     if conf.exists('location'):
         snmp['location'] = conf.return_value('location')
 
     if conf.exists('protocol'):
         snmp['protocol'] = conf.return_value('protocol')
 
     if conf.exists('smux-peer'):
         snmp['smux_peers'] = conf.return_values('smux-peer')
 
     if conf.exists('trap-source'):
         snmp['trap_source'] = conf.return_value('trap-source')
 
     if conf.exists('trap-target'):
         for target in conf.list_nodes('trap-target'):
             trap_tgt = {
                 'target': target,
                 'community': '',
                 'port': ''
             }
 
             if conf.exists('trap-target {0} community'.format(target)):
                trap_tgt['community'] = conf.return_value('trap-target {0} community'.format(target))
 
             if conf.exists('trap-target {0} port'.format(target)):
                 trap_tgt['port'] = conf.return_value('trap-target {0} port'.format(target))
 
             snmp['trap_targets'].append(trap_tgt)
 
     if conf.exists('script-extensions'):
         for extname in conf.list_nodes('script-extensions extension-name'):
             conf_script = conf.return_value('script-extensions extension-name {} script'.format(extname))
             # if script has not absolute path, use pre configured path
             if "/" not in conf_script:
                 conf_script = default_script_dir + conf_script
 
             extension = {
                 'name': extname,
                 'script' : conf_script
             }
 
             snmp['script_ext'].append(extension)
 
     if conf.exists('vrf'):
         # Append key to dict but don't place it in the default dictionary.
         # This is required to make the override.conf.tmpl work until we
         # migrate to get_config_dict().
         snmp['vrf'] = conf.return_value('vrf')
 
 
     #########################################################################
     #                ____  _   _ __  __ ____          _____                 #
     #               / ___|| \ | |  \/  |  _ \  __   _|___ /                 #
     #               \___ \|  \| | |\/| | |_) | \ \ / / |_ \                 #
     #                ___) | |\  | |  | |  __/   \ V / ___) |                #
     #               |____/|_| \_|_|  |_|_|       \_/ |____/                 #
     #                                                                       #
     #     now take care about the fancy SNMP v3 stuff, or bail out eraly    #
     #########################################################################
     if not conf.exists('v3'):
         return snmp
     else:
         snmp['v3_enabled'] = True
 
     # 'set service snmp v3 engineid'
     if conf.exists('v3 engineid'):
         snmp['v3_engineid'] = conf.return_value('v3 engineid')
 
     # 'set service snmp v3 group'
     if conf.exists('v3 group'):
         for group in conf.list_nodes('v3 group'):
             v3_group = {
                 'name': group,
                 'mode': 'ro',
                 'seclevel': 'auth',
                 'view': ''
             }
 
             if conf.exists('v3 group {0} mode'.format(group)):
                 v3_group['mode'] = conf.return_value('v3 group {0} mode'.format(group))
 
             if conf.exists('v3 group {0} seclevel'.format(group)):
                 v3_group['seclevel'] = conf.return_value('v3 group {0} seclevel'.format(group))
 
             if conf.exists('v3 group {0} view'.format(group)):
                 v3_group['view'] = conf.return_value('v3 group {0} view'.format(group))
 
             snmp['v3_groups'].append(v3_group)
 
     # 'set service snmp v3 trap-target'
     if conf.exists('v3 trap-target'):
         for trap in conf.list_nodes('v3 trap-target'):
             trap_cfg = {
                 'ipAddr': trap,
                 'secName': '',
                 'authProtocol': 'md5',
                 'authPassword': '',
                 'authMasterKey': '',
                 'privProtocol': 'des',
                 'privPassword': '',
                 'privMasterKey': '',
                 'ipProto': 'udp',
                 'ipPort': '162',
                 'type': '',
                 'secLevel': 'noAuthNoPriv'
             }
 
             if conf.exists('v3 trap-target {0} user'.format(trap)):
                 # Set the securityName used for authenticated SNMPv3 messages.
                 trap_cfg['secName'] = conf.return_value('v3 trap-target {0} user'.format(trap))
 
             if conf.exists('v3 trap-target {0} auth type'.format(trap)):
                 # Set the authentication protocol (MD5 or SHA) used for authenticated SNMPv3 messages
                 # cmdline option '-a'
                 trap_cfg['authProtocol'] = conf.return_value('v3 trap-target {0} auth type'.format(trap))
 
             if conf.exists('v3 trap-target {0} auth plaintext-password'.format(trap)):
                 # Set the authentication pass phrase used for authenticated SNMPv3 messages.
                 # cmdline option '-A'
                 trap_cfg['authPassword'] = conf.return_value('v3 trap-target {0} auth plaintext-password'.format(trap))
 
             if conf.exists('v3 trap-target {0} auth encrypted-password'.format(trap)):
                 # Sets the keys to be used for SNMPv3 transactions. These options allow you to set the master authentication keys.
                 # cmdline option '-3m'
                 trap_cfg['authMasterKey'] = conf.return_value('v3 trap-target {0} auth encrypted-password'.format(trap))
 
             if conf.exists('v3 trap-target {0} privacy type'.format(trap)):
                 # Set the privacy protocol (DES or AES) used for encrypted SNMPv3 messages.
                 # cmdline option '-x'
                 trap_cfg['privProtocol'] = conf.return_value('v3 trap-target {0} privacy type'.format(trap))
 
             if conf.exists('v3 trap-target {0} privacy plaintext-password'.format(trap)):
                 # Set the privacy pass phrase used for encrypted SNMPv3 messages.
                 # cmdline option '-X'
                 trap_cfg['privPassword'] = conf.return_value('v3 trap-target {0} privacy plaintext-password'.format(trap))
 
             if conf.exists('v3 trap-target {0} privacy encrypted-password'.format(trap)):
                 # Sets the keys to be used for SNMPv3 transactions. These options allow you to set the master encryption keys.
                 # cmdline option '-3M'
                 trap_cfg['privMasterKey'] = conf.return_value('v3 trap-target {0} privacy encrypted-password'.format(trap))
 
             if conf.exists('v3 trap-target {0} protocol'.format(trap)):
                 trap_cfg['ipProto'] = conf.return_value('v3 trap-target {0} protocol'.format(trap))
 
             if conf.exists('v3 trap-target {0} port'.format(trap)):
                 trap_cfg['ipPort'] = conf.return_value('v3 trap-target {0} port'.format(trap))
 
             if conf.exists('v3 trap-target {0} type'.format(trap)):
                 trap_cfg['type'] = conf.return_value('v3 trap-target {0} type'.format(trap))
 
             # Determine securityLevel used for SNMPv3 messages (noAuthNoPriv|authNoPriv|authPriv).
             # Appropriate pass phrase(s) must provided when using any level higher than noAuthNoPriv.
             if trap_cfg['authPassword'] or trap_cfg['authMasterKey']:
                 if trap_cfg['privProtocol'] or trap_cfg['privPassword']:
                     trap_cfg['secLevel'] = 'authPriv'
                 else:
                     trap_cfg['secLevel'] = 'authNoPriv'
 
             snmp['v3_traps'].append(trap_cfg)
 
     # 'set service snmp v3 user'
     if conf.exists('v3 user'):
         for user in conf.list_nodes('v3 user'):
             user_cfg = {
                 'name': user,
                 'authMasterKey': '',
                 'authPassword': '',
                 'authProtocol': 'md5',
                 'authOID': 'none',
                 'group': '',
                 'mode': 'ro',
                 'privMasterKey': '',
                 'privPassword': '',
                 'privOID': '',
                 'privProtocol': 'des'
             }
 
             # v3 user {0} auth
             if conf.exists('v3 user {0} auth encrypted-password'.format(user)):
                 user_cfg['authMasterKey'] = conf.return_value('v3 user {0} auth encrypted-password'.format(user))
 
             if conf.exists('v3 user {0} auth plaintext-password'.format(user)):
                 user_cfg['authPassword'] = conf.return_value('v3 user {0} auth plaintext-password'.format(user))
 
             # load default value
             type = user_cfg['authProtocol']
             if conf.exists('v3 user {0} auth type'.format(user)):
                 type = conf.return_value('v3 user {0} auth type'.format(user))
 
             # (re-)update with either default value or value from CLI
             user_cfg['authProtocol'] = type
             user_cfg['authOID'] = OIDs[type]
 
             # v3 user {0} group
             if conf.exists('v3 user {0} group'.format(user)):
                 user_cfg['group'] = conf.return_value('v3 user {0} group'.format(user))
 
             # v3 user {0} mode
             if conf.exists('v3 user {0} mode'.format(user)):
                 user_cfg['mode'] = conf.return_value('v3 user {0} mode'.format(user))
 
             # v3 user {0} privacy
             if conf.exists('v3 user {0} privacy encrypted-password'.format(user)):
                 user_cfg['privMasterKey'] = conf.return_value('v3 user {0} privacy encrypted-password'.format(user))
 
             if conf.exists('v3 user {0} privacy plaintext-password'.format(user)):
                 user_cfg['privPassword'] = conf.return_value('v3 user {0} privacy plaintext-password'.format(user))
 
             # load default value
             type = user_cfg['privProtocol']
             if conf.exists('v3 user {0} privacy type'.format(user)):
                 type = conf.return_value('v3 user {0} privacy type'.format(user))
 
             # (re-)update with either default value or value from CLI
             user_cfg['privProtocol'] = type
             user_cfg['privOID'] = OIDs[type]
 
             snmp['v3_users'].append(user_cfg)
 
     # 'set service snmp v3 view'
     if conf.exists('v3 view'):
         for view in conf.list_nodes('v3 view'):
             view_cfg = {
                 'name': view,
                 'oids': []
             }
 
             if conf.exists('v3 view {0} oid'.format(view)):
                 for oid in conf.list_nodes('v3 view {0} oid'.format(view)):
                     oid_cfg = {
                         'oid': oid
                     }
+                    if conf.exists('v3 view {0} oid {1} exclude'.format(view, oid)):
+                        oid_cfg['exclude'] = conf.return_values('v3 view {0} oid {1} exclude'.format(view, oid))
                     view_cfg['oids'].append(oid_cfg)
             snmp['v3_views'].append(view_cfg)
 
     return snmp
 
 def verify(snmp):
     if snmp is None:
         # we can not delete SNMP when LLDP is configured with SNMP
         conf = Config()
         if conf.exists('service lldp snmp enable'):
             raise ConfigError('Can not delete SNMP service, as LLDP still uses SNMP!')
 
         return None
 
     ### check if the configured script actually exist
     if snmp['script_ext']:
         for ext in snmp['script_ext']:
             if not os.path.isfile(ext['script']):
                 print ("WARNING: script: {} doesn't exist".format(ext['script']))
             else:
                 chmod_755(ext['script'])
 
     for listen in snmp['listen_address']:
         addr = listen[0]
         port = listen[1]
         protocol = snmp['protocol']
 
         tmp = None
         if is_ipv4(addr):
             # example: udp:127.0.0.1:161
             tmp = f'{protocol}:{addr}:{port}'
         elif snmp['ipv6_enabled']:
             # example: udp6:[::1]:161
             tmp = f'{protocol}6:[{addr}]:{port}'
 
         # We only wan't to configure addresses that exist on the system.
         # Hint the user if they don't exist
         if is_addr_assigned(addr):
             if tmp: snmp['listen_on'].append(tmp)
         else:
             print(f'WARNING: SNMP listen address {addr} not configured!')
 
     verify_vrf(snmp)
 
     # bail out early if SNMP v3 is not configured
     if not snmp['v3_enabled']:
         return None
 
     if 'v3_groups' in snmp.keys():
         for group in snmp['v3_groups']:
             #
             # A view must exist prior to mapping it into a group
             #
             if 'view' in group.keys():
                 error = True
                 if 'v3_views' in snmp.keys():
                     for view in snmp['v3_views']:
                         if view['name'] == group['view']:
                             error = False
                 if error:
                     raise ConfigError('You must create view "{0}" first'.format(group['view']))
             else:
                 raise ConfigError('"view" must be specified')
 
             if not 'mode' in group.keys():
                 raise ConfigError('"mode" must be specified')
 
             if not 'seclevel' in group.keys():
                 raise ConfigError('"seclevel" must be specified')
 
     if 'v3_traps' in snmp.keys():
         for trap in snmp['v3_traps']:
             if trap['authPassword'] and trap['authMasterKey']:
                 raise ConfigError('Must specify only one of encrypted-password/plaintext-key for trap auth')
 
             if trap['authPassword'] == '' and trap['authMasterKey'] == '':
                 raise ConfigError('Must specify encrypted-password or plaintext-key for trap auth')
 
             if trap['privPassword'] and trap['privMasterKey']:
                 raise ConfigError('Must specify only one of encrypted-password/plaintext-key for trap privacy')
 
             if trap['privPassword'] == '' and trap['privMasterKey'] == '':
                 raise ConfigError('Must specify encrypted-password or plaintext-key for trap privacy')
 
             if not 'type' in trap.keys():
                 raise ConfigError('v3 trap: "type" must be specified')
 
             if not 'authPassword' and 'authMasterKey' in trap.keys():
                 raise ConfigError('v3 trap: "auth" must be specified')
 
             if not 'authProtocol' in trap.keys():
                 raise ConfigError('v3 trap: "protocol" must be specified')
 
             if not 'privPassword' and 'privMasterKey' in trap.keys():
                 raise ConfigError('v3 trap: "user" must be specified')
 
     if 'v3_users' in snmp.keys():
         for user in snmp['v3_users']:
             #
             # Group must exist prior to mapping it into a group
             # seclevel will be extracted from group
             #
             if 'group' not in user or user['group'] == '':
                 username = user['name']
                 raise ConfigError(f'Group membership required for user "{username}"!')
 
             if user['group']:
                 error = True
                 if 'v3_groups' in snmp.keys():
                     for group in snmp['v3_groups']:
                         if group['name'] == user['group']:
                             seclevel = group['seclevel']
                             error = False
 
                 if error:
                     raise ConfigError('You must create group "{0}" first'.format(user['group']))
 
             # Depending on the configured security level the user has to provide additional info
             if (not user['authPassword'] and not user['authMasterKey']):
                 raise ConfigError('Must specify encrypted-password or plaintext-key for user auth')
 
             if user['privPassword'] == '' and user['privMasterKey'] == '':
                 raise ConfigError('Must specify encrypted-password or plaintext-key for user privacy')
 
             if user['mode'] == '':
                 raise ConfigError('Must specify user mode ro/rw')
 
     if 'v3_views' in snmp.keys():
         for view in snmp['v3_views']:
             if not view['oids']:
                 raise ConfigError('Must configure an oid')
 
     return None
 
 def generate(snmp):
     #
     # As we are manipulating the snmpd user database we have to stop it first!
     # This is even save if service is going to be removed
     call('systemctl stop snmpd.service')
     config_files = [config_file_client, config_file_daemon, config_file_access,
                     config_file_user, systemd_override]
     for file in config_files:
         rmfile(file)
 
     if not snmp:
         return None
 
     if 'v3_users' in snmp.keys():
         # net-snmp is now regenerating the configuration file in the background
         # thus we need to re-open and re-read the file as the content changed.
         # After that we can no read the encrypted password from the config and
         # replace the CLI plaintext password with its encrypted version.
         os.environ["vyos_libexec_dir"] = "/usr/libexec/vyos"
 
         for user in snmp['v3_users']:
             if user['authProtocol'] == 'sha':
                 hash = plaintext_to_sha1
             else:
                 hash = plaintext_to_md5
 
             if user['authPassword']:
                 user['authMasterKey'] = hash(user['authPassword'], snmp['v3_engineid'])
                 user['authPassword'] = ''
 
                 call('/opt/vyatta/sbin/my_set service snmp v3 user "{name}" auth encrypted-password "{authMasterKey}" > /dev/null'.format(**user))
                 call('/opt/vyatta/sbin/my_delete service snmp v3 user "{name}" auth plaintext-password > /dev/null'.format(**user))
 
             if user['privPassword']:
                 user['privMasterKey'] = hash(user['privPassword'], snmp['v3_engineid'])
                 user['privPassword'] = ''
 
                 call('/opt/vyatta/sbin/my_set service snmp v3 user "{name}" privacy encrypted-password "{privMasterKey}" > /dev/null'.format(**user))
                 call('/opt/vyatta/sbin/my_delete service snmp v3 user "{name}" privacy plaintext-password > /dev/null'.format(**user))
 
     # Write client config file
     render(config_file_client, 'snmp/etc.snmp.conf.tmpl', snmp)
     # Write server config file
     render(config_file_daemon, 'snmp/etc.snmpd.conf.tmpl', snmp)
     # Write access rights config file
     render(config_file_access, 'snmp/usr.snmpd.conf.tmpl', snmp)
     # Write access rights config file
     render(config_file_user, 'snmp/var.snmpd.conf.tmpl', snmp)
     # Write daemon configuration file
     render(systemd_override, 'snmp/override.conf.tmpl', snmp)
 
     return None
 
 def apply(snmp):
     # Always reload systemd manager configuration
     call('systemctl daemon-reload')
 
     if not snmp:
         return None
 
     # start SNMP daemon
     call('systemctl restart snmpd.service')
 
     # Enable AgentX in FRR
     call('vtysh -c "configure terminal" -c "agentx" >/dev/null')
 
     return None
 
 if __name__ == '__main__':
     try:
         c = get_config()
         verify(c)
         generate(c)
         apply(c)
     except ConfigError as e:
         print(e)
         exit(1)