/* * Copyright (c) 2013 Big Switch Networks, Inc. * * Licensed under the Eclipse Public License, Version 1.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package org.sdnplatform.forwarding; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.sdnplatform.addressspace.IAddressSpaceManagerService; import org.sdnplatform.core.ListenerContext; import org.sdnplatform.core.ListenerContextStore; import org.sdnplatform.core.module.ModuleContext; import org.sdnplatform.core.module.ModuleException; import org.sdnplatform.core.module.IModule; import org.sdnplatform.core.module.IPlatformService; import org.sdnplatform.devicemanager.SwitchPort; public class RewriteServiceImpl implements IRewriteService, IModule { protected static final String REWRITE_RULE = "org.sdnplatform.forwarding.rewrite_rule"; protected static final ListenerContextStore<RewriteRule> rwStore = new ListenerContextStore<RewriteRule>(); protected class RewriteRule { protected Long origDstMac; protected Long finalDstMac; protected Long origSrcMac; protected Long finalSrcMac; protected Integer ttlDecrement; protected Short transportVlan; } protected IAddressSpaceManagerService addressSpaceManager; protected RewriteRule getRuleFromContext(ListenerContext cntx) throws NullPointerException { RewriteRule rule; if (cntx == null) throw new NullPointerException("cntx cannot be null"); rule = rwStore.get(cntx, REWRITE_RULE); if (rule == null) { // no rules in context yet rule = new RewriteRule(); rwStore.put(cntx, REWRITE_RULE, rule); } return rule; } protected RewriteRule getRuleFromContextIfExists(ListenerContext cntx) throws NullPointerException { RewriteRule rule; if (cntx == null) throw new NullPointerException("cntx cannot be null"); rule = rwStore.get(cntx, REWRITE_RULE); return rule; } /********************* * IRewriteService ********************/ @Override public boolean hasRewriteRules(ListenerContext cntx) throws NullPointerException { RewriteRule rule = getRuleFromContextIfExists(cntx); if (rule == null) return false; return (rule.origDstMac != null || rule.finalDstMac != null || rule.origSrcMac != null || rule.finalSrcMac != null || rule.ttlDecrement != null || rule.transportVlan != null ); } @Override public Short getSwitchPortVlanMode(SwitchPort swp, String addressSpaceName, Short currentVlan, boolean tunnelEnabled) throws NullPointerException, IllegalArgumentException { // address space manager will do sanity checking of the args return addressSpaceManager.getSwitchPortVlanMode(swp, addressSpaceName, currentVlan, tunnelEnabled); } @Override public void setIngressDstMac(Long origMac, Long finalMac, ListenerContext cntx) throws NullPointerException { if (origMac == null) throw new NullPointerException("origMac cannot be null"); if (finalMac == null) throw new NullPointerException("newMac cannot be null"); RewriteRule rule = getRuleFromContext(cntx); if (origMac.equals(finalMac)) return; rule.origDstMac = origMac; rule.finalDstMac = finalMac; // no need to put it into the cntx again. it's already there } @Override public Long getOrigIngressDstMac(ListenerContext cntx) throws NullPointerException { RewriteRule rule = getRuleFromContextIfExists(cntx); if (rule == null) return null; return rule.origDstMac; } @Override public Long getFinalIngressDstMac(ListenerContext cntx) throws NullPointerException { RewriteRule rule = getRuleFromContextIfExists(cntx); if (rule == null) return null; return rule.finalDstMac; } @Override public void clearIngressDstMac(ListenerContext cntx) throws NullPointerException { RewriteRule rule = getRuleFromContextIfExists(cntx); if (rule == null) return; rule.origDstMac = null; rule.finalDstMac = null; } @Override public void setTransportVlan(Short vlan, ListenerContext cntx) throws NullPointerException, IllegalArgumentException { if (vlan == null) throw new NullPointerException("vlan cannot be null"); /* boolean isValidVlan = (vlan>0 && vlan<4096 || vlan.equals(Ethernet.VLAN_UNTAGGED)); */ boolean isValidVlan = (vlan>0 && vlan<4096); if (!isValidVlan) throw new IllegalArgumentException("Invalid VLAN " + vlan); RewriteRule rule = getRuleFromContext(cntx); rule.transportVlan = vlan; // no need to put it into the cntx again. it's already there } @Override public Short getTransportVlan(ListenerContext cntx) throws NullPointerException { RewriteRule rule = getRuleFromContextIfExists(cntx); if (rule == null) return null; return rule.transportVlan; } @Override public void clearTransportVlan(ListenerContext cntx) throws NullPointerException { RewriteRule rule = getRuleFromContextIfExists(cntx); if (rule == null) return; rule.transportVlan = null; } @Override public void setEgressSrcMac(Long origMac, Long finalMac, ListenerContext cntx) throws NullPointerException { if (origMac == null) throw new NullPointerException("origMac cannot be null"); if (finalMac == null) throw new NullPointerException("newMac cannot be null"); RewriteRule rule = getRuleFromContext(cntx); if (origMac.equals(finalMac)) return; rule.origSrcMac = origMac; rule.finalSrcMac = finalMac; // no need to put it into the cntx again. it's already there } @Override public Long getOrigEgressSrcMac(ListenerContext cntx) throws NullPointerException { RewriteRule rule = getRuleFromContextIfExists(cntx); if (rule == null) return null; return rule.origSrcMac; } @Override public Long getFinalEgressSrcMac(ListenerContext cntx) throws NullPointerException { RewriteRule rule = getRuleFromContextIfExists(cntx); if (rule == null) return null; return rule.finalSrcMac; } @Override public void clearEgressSrcMac(ListenerContext cntx) throws NullPointerException { RewriteRule rule = getRuleFromContextIfExists(cntx); if (rule == null) return; rule.origSrcMac = null; rule.finalSrcMac = null; } @Override public void setTtlDecrement(int numHops, ListenerContext cntx) throws NullPointerException { if (numHops <= 0 || numHops >= 255) { throw new IllegalArgumentException( "Number of hops for TTL decrement must be > 0" + " and < 255"); } RewriteRule rule = getRuleFromContext(cntx); rule.ttlDecrement = numHops; } @Override public Integer getTtlDecrement(ListenerContext cntx) throws NullPointerException { RewriteRule rule = getRuleFromContextIfExists(cntx); if (rule == null) return null; return rule.ttlDecrement; } @Override public void clearTtlDecrement(ListenerContext cntx) throws NullPointerException { RewriteRule rule = getRuleFromContextIfExists(cntx); if (rule == null) return; rule.ttlDecrement = null; } /********************* * IModule ********************/ @Override public Collection<Class<? extends IPlatformService>> getModuleServices() { Collection<Class<? extends IPlatformService>> l = new ArrayList<Class<? extends IPlatformService>>(); l.add(IRewriteService.class); return l; } @Override public Map<Class<? extends IPlatformService>, IPlatformService> getServiceImpls() { Map<Class<? extends IPlatformService>, IPlatformService> m = new HashMap<Class<? extends IPlatformService>, IPlatformService>(); // We are the class that implements the service m.put(IRewriteService.class, this); return m; } @Override public Collection<Class<? extends IPlatformService>> getModuleDependencies() { Collection<Class<? extends IPlatformService>> l = new ArrayList<Class<? extends IPlatformService>>(); l.add(IAddressSpaceManagerService.class); return l; } @Override public void init(ModuleContext context) throws ModuleException { addressSpaceManager = context.getServiceImpl(IAddressSpaceManagerService.class); } @Override public void startUp(ModuleContext context) { // no-op } }